Fix memory leak with PlaybackViewModel
Fix a memory leak involving a stray context that PlaybackViewModel would store.
This commit is contained in:
parent
85475b5c61
commit
3251b84e23
13 changed files with 29 additions and 57 deletions
|
@ -23,9 +23,10 @@
|
|||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<service android:name=".playback.PlaybackService"
|
||||
<service
|
||||
android:name=".playback.PlaybackService"
|
||||
android:icon="@drawable/ic_launcher_foreground"
|
||||
android:description="@string/description_service_playback"
|
||||
android:description="@string/label_service_playback"
|
||||
android:stopWithTask="false" />
|
||||
</application>
|
||||
</manifest>
|
|
@ -1,5 +1,6 @@
|
|||
package org.oxycblt.auxio
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
|
@ -15,6 +16,7 @@ import com.google.android.material.tabs.TabLayoutMediator
|
|||
import org.oxycblt.auxio.databinding.FragmentMainBinding
|
||||
import org.oxycblt.auxio.library.LibraryFragment
|
||||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.playback.PlaybackService
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.songs.SongsFragment
|
||||
import org.oxycblt.auxio.theme.accent
|
||||
|
@ -23,9 +25,7 @@ import org.oxycblt.auxio.theme.getTransparentAccent
|
|||
import org.oxycblt.auxio.theme.toColor
|
||||
|
||||
class MainFragment : Fragment() {
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels {
|
||||
PlaybackViewModel.Factory(requireContext())
|
||||
}
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||
|
||||
private val shownFragments = listOf(0, 1)
|
||||
private val tabIcons = listOf(
|
||||
|
@ -105,6 +105,11 @@ class MainFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
// Start the playback service.
|
||||
Intent(requireContext(), PlaybackService::class.java).also {
|
||||
requireContext().startService(it)
|
||||
}
|
||||
|
||||
Log.d(this::class.simpleName, "Fragment Created.")
|
||||
|
||||
return binding.root
|
||||
|
|
|
@ -22,9 +22,7 @@ class AlbumDetailFragment : Fragment() {
|
|||
|
||||
private val args: AlbumDetailFragmentArgs by navArgs()
|
||||
private val detailModel: DetailViewModel by activityViewModels()
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels {
|
||||
PlaybackViewModel.Factory(requireContext())
|
||||
}
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
|
|
|
@ -20,9 +20,7 @@ import org.oxycblt.auxio.theme.disable
|
|||
class ArtistDetailFragment : Fragment() {
|
||||
private val args: ArtistDetailFragmentArgs by navArgs()
|
||||
private val detailModel: DetailViewModel by activityViewModels()
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels {
|
||||
PlaybackViewModel.Factory(requireContext())
|
||||
}
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
|
|
|
@ -21,9 +21,7 @@ class GenreDetailFragment : Fragment() {
|
|||
|
||||
private val args: GenreDetailFragmentArgs by navArgs()
|
||||
private val detailModel: DetailViewModel by activityViewModels()
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels {
|
||||
PlaybackViewModel.Factory(requireContext())
|
||||
}
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
|
|
|
@ -35,9 +35,7 @@ import org.oxycblt.auxio.theme.resolveAttr
|
|||
class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
|
||||
|
||||
private val libraryModel: LibraryViewModel by activityViewModels()
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels {
|
||||
PlaybackViewModel.Factory(requireContext())
|
||||
}
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
|
|
|
@ -16,9 +16,7 @@ import org.oxycblt.auxio.databinding.FragmentCompactPlaybackBinding
|
|||
import org.oxycblt.auxio.music.MusicStore
|
||||
|
||||
class CompactPlaybackFragment : Fragment() {
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels {
|
||||
PlaybackViewModel.Factory(requireContext())
|
||||
}
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
|
|
|
@ -22,9 +22,7 @@ import org.oxycblt.auxio.theme.toColor
|
|||
|
||||
// TODO: Add a swipe-to-next-track function using a ViewPager
|
||||
class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels {
|
||||
PlaybackViewModel.Factory(requireActivity().application)
|
||||
}
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||
|
||||
// TODO: Implement nav to artists/albums
|
||||
override fun onCreateView(
|
||||
|
|
|
@ -139,12 +139,13 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateCallback {
|
|||
}
|
||||
|
||||
private fun createNotification(): Notification {
|
||||
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
val notificationManager =
|
||||
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val channel = NotificationChannel(
|
||||
CHANNEL_ID,
|
||||
getString(R.string.description_playback),
|
||||
getString(R.string.label_notif_playback),
|
||||
NotificationManager.IMPORTANCE_DEFAULT
|
||||
)
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
|
@ -156,7 +157,7 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateCallback {
|
|||
)
|
||||
.setSmallIcon(R.drawable.ic_song)
|
||||
.setContentTitle(getString(R.string.app_name))
|
||||
.setContentText(getString(R.string.description_playback))
|
||||
.setContentText(getString(R.string.label_is_playing))
|
||||
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
||||
.setChannelId(CHANNEL_ID)
|
||||
.build()
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
package org.oxycblt.auxio.playback
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.Transformations
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.Genre
|
||||
|
@ -21,7 +18,7 @@ import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
|||
// TODO: Implement Looping Modes
|
||||
// TODO: Implement User Queue
|
||||
// TODO: Implement Persistence through Bundles/Databases/Idk
|
||||
class PlaybackViewModel(private val context: Context) : ViewModel(), PlaybackStateCallback {
|
||||
class PlaybackViewModel() : ViewModel(), PlaybackStateCallback {
|
||||
// Playback
|
||||
private val mSong = MutableLiveData<Song>()
|
||||
val song: LiveData<Song> get() = mSong
|
||||
|
@ -66,13 +63,6 @@ class PlaybackViewModel(private val context: Context) : ViewModel(), PlaybackSta
|
|||
private val playbackManager = PlaybackStateManager.getInstance()
|
||||
|
||||
init {
|
||||
// Start the service from the ViewModel.
|
||||
// Yes, I know ViewModels aren't supposed to deal with this stuff but for some
|
||||
// reason it only works here.
|
||||
Intent(context, PlaybackService::class.java).also {
|
||||
context.startService(it)
|
||||
}
|
||||
|
||||
playbackManager.addCallback(this)
|
||||
|
||||
// If the PlaybackViewModel was cleared [signified by the PlaybackStateManager having a
|
||||
|
@ -233,6 +223,8 @@ class PlaybackViewModel(private val context: Context) : ViewModel(), PlaybackSta
|
|||
}
|
||||
|
||||
private fun restorePlaybackState() {
|
||||
Log.d(this::class.simpleName, "Attempting to restore playback state.")
|
||||
|
||||
mSong.value = playbackManager.song
|
||||
mPosition.value = playbackManager.position
|
||||
mQueue.value = playbackManager.queue
|
||||
|
@ -240,15 +232,4 @@ class PlaybackViewModel(private val context: Context) : ViewModel(), PlaybackSta
|
|||
mIsPlaying.value = playbackManager.isPlaying
|
||||
mIsShuffling.value = playbackManager.isShuffling
|
||||
}
|
||||
|
||||
class Factory(private val context: Context) : ViewModelProvider.Factory {
|
||||
@Suppress("unchecked_cast")
|
||||
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
|
||||
if (modelClass.isAssignableFrom(PlaybackViewModel::class.java)) {
|
||||
return PlaybackViewModel(context) as T
|
||||
}
|
||||
|
||||
throw IllegalArgumentException("Unknown ViewModel class.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,7 @@ import org.oxycblt.auxio.theme.applyDivider
|
|||
import org.oxycblt.auxio.theme.toColor
|
||||
|
||||
class QueueFragment : BottomSheetDialogFragment() {
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels {
|
||||
PlaybackViewModel.Factory(requireActivity().application)
|
||||
}
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||
|
||||
override fun getTheme(): Int = R.style.Theme_BottomSheetFix
|
||||
|
||||
|
|
|
@ -15,9 +15,7 @@ import org.oxycblt.auxio.playback.state.PlaybackMode
|
|||
import org.oxycblt.auxio.theme.applyDivider
|
||||
|
||||
class SongsFragment : Fragment() {
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels {
|
||||
PlaybackViewModel.Factory(requireContext())
|
||||
}
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
<string name="label_play">Play</string>
|
||||
<string name="label_queue">Queue</string>
|
||||
<string name="label_queue_add">Add to queue</string>
|
||||
<string name="label_notif_playback">Music Playback</string>
|
||||
<string name="label_service_playback">The music playback service for Auxio.</string>
|
||||
<string name="label_is_playing">Auxio is playing music</string>
|
||||
|
||||
<!-- Hint Namespace | EditText Hints -->
|
||||
<string name="hint_search_library">Search Library…</string>
|
||||
|
@ -47,9 +50,6 @@
|
|||
<string name="description_skip_prev">Skip to last song</string>
|
||||
<string name="description_shuffle_on">Turn shuffle on</string>
|
||||
<string name="description_shuffle_off">Turn shuffle off</string>
|
||||
<string name="description_service_playback">The music playback service for Auxio</string>
|
||||
<string name="description_notif_playback">Music Playback</string>
|
||||
<string name="description_playback">Auxio is playing music</string>
|
||||
|
||||
<!-- Placeholder Namespace | Placeholder values -->
|
||||
<string name="placeholder_genre">Unknown Genre</string>
|
||||
|
|
Loading…
Reference in a new issue