Update stored DetailViewModel items
Change the stored items in DetailViewModel to LiveData. Remove the need to reset the stored items when a fragment is destroyed.
This commit is contained in:
parent
d9cf3772e6
commit
af4c32eb5b
13 changed files with 65 additions and 83 deletions
|
@ -24,19 +24,12 @@ TODO:
|
|||
|
||||
/library/
|
||||
|
||||
- Add genres
|
||||
- ? Move into ViewPager ?
|
||||
- Sorting
|
||||
- Search
|
||||
- ? Show Artists, Albums, and Songs in search ?
|
||||
- Exit functionality
|
||||
|
||||
/other/
|
||||
|
||||
- ? Condense detail fragments into a single fragment ?
|
||||
- Condense artist/album recyclerview items into single item
|
||||
- Remove binding adapters
|
||||
|
||||
To be added:
|
||||
/prefs/
|
||||
/playback/
|
|
@ -33,12 +33,14 @@ class AlbumDetailFragment : Fragment() {
|
|||
|
||||
// If DetailViewModel isn't already storing the album, get it from MusicViewModel
|
||||
// using the ID given by the navigation arguments.
|
||||
if (detailModel.currentAlbum == null) {
|
||||
if (detailModel.currentAlbum.value!!.id != args.albumId) {
|
||||
val musicModel: MusicViewModel by activityViewModels()
|
||||
|
||||
detailModel.currentAlbum = musicModel.albums.value!!.find {
|
||||
it.id == args.albumId
|
||||
}!!
|
||||
detailModel.updateAlbum(
|
||||
musicModel.albums.value!!.find {
|
||||
it.id == args.albumId
|
||||
}!!
|
||||
)
|
||||
}
|
||||
|
||||
val songAdapter = DetailSongAdapter(
|
||||
|
@ -49,7 +51,7 @@ class AlbumDetailFragment : Fragment() {
|
|||
|
||||
binding.lifecycleOwner = this
|
||||
binding.detailModel = detailModel
|
||||
binding.album = detailModel.currentAlbum
|
||||
binding.album = detailModel.currentAlbum.value!!
|
||||
|
||||
binding.albumSongRecycler.apply {
|
||||
adapter = songAdapter
|
||||
|
@ -61,20 +63,16 @@ class AlbumDetailFragment : Fragment() {
|
|||
findNavController().navigateUp()
|
||||
}
|
||||
|
||||
// If the album was shown directly from LibraryFragment [No parent artist stored],
|
||||
// then enable the ability to navigate upwards to the album's parent artist.
|
||||
if (detailModel.currentArtist == null) {
|
||||
detailModel.doneWithNavToParent()
|
||||
|
||||
detailModel.navToParentArtist.observe(viewLifecycleOwner) {
|
||||
if (it) {
|
||||
// If the album was shown directly from LibraryFragment [No parent artist stored]
|
||||
// Then enable the ability to navigate upwards to the parent artist
|
||||
if (detailModel.currentArtist.value!!.id != detailModel.currentAlbum.value!!.artist.id) {
|
||||
detailModel.currentArtist.observe(viewLifecycleOwner) {
|
||||
if (it.id == detailModel.currentAlbum.value!!.artist.id) {
|
||||
findNavController().navigate(
|
||||
AlbumDetailFragmentDirections.actionShowParentArtist(
|
||||
detailModel.currentAlbum!!.artist.id
|
||||
detailModel.currentAlbum.value!!.artist.id
|
||||
)
|
||||
)
|
||||
|
||||
detailModel.doneWithNavToParent()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,7 +85,7 @@ class AlbumDetailFragment : Fragment() {
|
|||
|
||||
// Then update the sort mode of the album adapter.
|
||||
songAdapter.submitList(
|
||||
detailModel.currentAlbum!!.songs.sortedWith(
|
||||
detailModel.currentAlbum.value!!.songs.sortedWith(
|
||||
SortMode.songSortComparators.getOrDefault(
|
||||
mode,
|
||||
|
||||
|
@ -99,7 +97,7 @@ class AlbumDetailFragment : Fragment() {
|
|||
}
|
||||
|
||||
// Don't enable the sort button if there's only one song [or less]
|
||||
if (detailModel.currentAlbum!!.numSongs < 2) {
|
||||
if (detailModel.currentAlbum.value!!.numSongs < 2) {
|
||||
binding.albumSortButton.imageTintList = ColorStateList.valueOf(
|
||||
R.color.inactive_color.toColor(requireContext())
|
||||
)
|
||||
|
@ -111,10 +109,4 @@ class AlbumDetailFragment : Fragment() {
|
|||
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
|
||||
detailModel.currentAlbum = null
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,11 +34,14 @@ class ArtistDetailFragment : Fragment() {
|
|||
|
||||
// If DetailViewModel isn't already storing the artist, get it from MusicViewModel
|
||||
// using the ID given by the navigation arguments
|
||||
if (detailModel.currentArtist == null) {
|
||||
if (detailModel.currentArtist.value!!.id != args.artistId) {
|
||||
val musicModel: MusicViewModel by activityViewModels()
|
||||
detailModel.currentArtist = musicModel.artists.value!!.find {
|
||||
it.id == args.artistId
|
||||
}!!
|
||||
|
||||
detailModel.updateArtist(
|
||||
musicModel.artists.value!!.find {
|
||||
it.id == args.artistId
|
||||
}!!
|
||||
)
|
||||
}
|
||||
|
||||
val albumAdapter = DetailAlbumAdapter(
|
||||
|
@ -49,7 +52,7 @@ class ArtistDetailFragment : Fragment() {
|
|||
|
||||
binding.lifecycleOwner = this
|
||||
binding.detailModel = detailModel
|
||||
binding.artist = detailModel.currentArtist!!
|
||||
binding.artist = detailModel.currentArtist.value!!
|
||||
|
||||
binding.artistAlbumRecycler.apply {
|
||||
adapter = albumAdapter
|
||||
|
@ -67,7 +70,7 @@ class ArtistDetailFragment : Fragment() {
|
|||
|
||||
// Then update the sort mode of the album adapter.
|
||||
albumAdapter.submitList(
|
||||
detailModel.currentArtist!!.albums.sortedWith(
|
||||
detailModel.currentArtist.value!!.albums.sortedWith(
|
||||
SortMode.albumSortComparators.getOrDefault(
|
||||
mode,
|
||||
|
||||
|
@ -79,7 +82,7 @@ class ArtistDetailFragment : Fragment() {
|
|||
}
|
||||
|
||||
// Don't enable the sort button if there is only one album [Or less]
|
||||
if (detailModel.currentArtist!!.numAlbums < 2) {
|
||||
if (detailModel.currentArtist.value!!.numAlbums < 2) {
|
||||
binding.artistSortButton.imageTintList = ColorStateList.valueOf(
|
||||
R.color.inactive_color.toColor(requireContext())
|
||||
)
|
||||
|
@ -98,14 +101,6 @@ class ArtistDetailFragment : Fragment() {
|
|||
detailModel.isAlreadyNavigating = false
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
|
||||
// Reset the stored artist so that the next instance of ArtistDetailFragment
|
||||
// will not read it.
|
||||
detailModel.currentArtist = null
|
||||
}
|
||||
|
||||
private fun navToAlbum(album: Album) {
|
||||
// Don't navigate if an item already has been selected.
|
||||
if (!detailModel.isAlreadyNavigating) {
|
||||
|
|
|
@ -11,9 +11,6 @@ import org.oxycblt.auxio.recycler.SortMode
|
|||
class DetailViewModel : ViewModel() {
|
||||
var isAlreadyNavigating = false
|
||||
|
||||
private val mNavToParentArtist = MutableLiveData<Boolean>()
|
||||
val navToParentArtist: LiveData<Boolean> get() = mNavToParentArtist
|
||||
|
||||
private val mGenreSortMode = MutableLiveData(SortMode.ALPHA_DOWN)
|
||||
val genreSortMode: LiveData<SortMode> get() = mGenreSortMode
|
||||
|
||||
|
@ -23,16 +20,28 @@ class DetailViewModel : ViewModel() {
|
|||
private val mAlbumSortMode = MutableLiveData(SortMode.NUMERIC_DOWN)
|
||||
val albumSortMode: LiveData<SortMode> get() = mAlbumSortMode
|
||||
|
||||
var currentGenre: Genre? = null
|
||||
var currentArtist: Artist? = null
|
||||
var currentAlbum: Album? = null
|
||||
// Current music models being shown
|
||||
// These have placeholder values in them so that they don't
|
||||
// have to be checked if they're null.
|
||||
private val mCurrentGenre = MutableLiveData(Genre(name = ""))
|
||||
val currentGenre: LiveData<Genre> get() = mCurrentGenre
|
||||
|
||||
fun navToParent() {
|
||||
mNavToParentArtist.value = true
|
||||
private val mCurrentArtist = MutableLiveData(Artist(name = ""))
|
||||
val currentArtist: LiveData<Artist> get() = mCurrentArtist
|
||||
|
||||
private val mCurrentAlbum = MutableLiveData(Album(name = "", artistName = ""))
|
||||
val currentAlbum: LiveData<Album> get() = mCurrentAlbum
|
||||
|
||||
fun updateGenre(genre: Genre) {
|
||||
mCurrentGenre.value = genre
|
||||
}
|
||||
|
||||
fun doneWithNavToParent() {
|
||||
mNavToParentArtist.value = false
|
||||
fun updateArtist(artist: Artist) {
|
||||
mCurrentArtist.value = artist
|
||||
}
|
||||
|
||||
fun updateAlbum(album: Album) {
|
||||
mCurrentAlbum.value = album
|
||||
}
|
||||
|
||||
fun incrementGenreSortMode() {
|
||||
|
|
|
@ -34,11 +34,14 @@ class GenreDetailFragment : Fragment() {
|
|||
|
||||
// If DetailViewModel isn't already storing the genre, get it from MusicViewModel
|
||||
// using the ID given by the navigation arguments
|
||||
if (detailModel.currentGenre == null) {
|
||||
if (detailModel.currentGenre.value!!.id != args.genreId) {
|
||||
val musicModel: MusicViewModel by activityViewModels()
|
||||
detailModel.currentGenre = musicModel.genres.value!!.find {
|
||||
it.id == args.genreId
|
||||
}!!
|
||||
|
||||
detailModel.updateGenre(
|
||||
musicModel.genres.value!!.find {
|
||||
it.id == args.genreId
|
||||
}!!
|
||||
)
|
||||
}
|
||||
|
||||
val albumAdapter = DetailArtistAdapter(
|
||||
|
@ -49,7 +52,7 @@ class GenreDetailFragment : Fragment() {
|
|||
|
||||
binding.lifecycleOwner = this
|
||||
binding.detailModel = detailModel
|
||||
binding.genre = detailModel.currentGenre!!
|
||||
binding.genre = detailModel.currentGenre.value
|
||||
|
||||
binding.genreArtistRecycler.adapter = albumAdapter
|
||||
binding.genreArtistRecycler.applyDivider()
|
||||
|
@ -63,9 +66,9 @@ class GenreDetailFragment : Fragment() {
|
|||
// Update the current sort icon
|
||||
binding.genreSortButton.setImageResource(mode.iconRes)
|
||||
|
||||
// Then update the sort mode of the album adapter.
|
||||
// Then update the sort mode of the artist adapter.
|
||||
albumAdapter.submitList(
|
||||
detailModel.currentGenre!!.artists.sortedWith(
|
||||
detailModel.currentGenre.value!!.artists.sortedWith(
|
||||
SortMode.artistSortComparators.getOrDefault(
|
||||
mode,
|
||||
|
||||
|
@ -77,7 +80,7 @@ class GenreDetailFragment : Fragment() {
|
|||
}
|
||||
|
||||
// Don't enable the sort button if there is only one artist [Or less]
|
||||
if (detailModel.currentGenre!!.numArtists < 2) {
|
||||
if (detailModel.currentGenre.value!!.numArtists < 2) {
|
||||
binding.genreSortButton.imageTintList = ColorStateList.valueOf(
|
||||
R.color.inactive_color.toColor(requireContext())
|
||||
)
|
||||
|
@ -96,14 +99,6 @@ class GenreDetailFragment : Fragment() {
|
|||
detailModel.isAlreadyNavigating = false
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
|
||||
// Reset the stored artist so that the next instance of GenreDetailFragment
|
||||
// will not read it.
|
||||
detailModel.currentGenre = null
|
||||
}
|
||||
|
||||
private fun navToArtist(artist: Artist) {
|
||||
// Don't navigate if an item already has been selected.
|
||||
if (!detailModel.isAlreadyNavigating) {
|
||||
|
|
|
@ -3,9 +3,7 @@ package org.oxycblt.auxio.detail.adapters
|
|||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import org.oxycblt.auxio.databinding.ItemAlbumBinding
|
||||
import org.oxycblt.auxio.databinding.ItemArtistAlbumBinding
|
||||
import org.oxycblt.auxio.databinding.ItemArtistBinding
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.recycler.BaseViewHolder
|
||||
import org.oxycblt.auxio.recycler.ClickListener
|
||||
|
|
|
@ -3,10 +3,8 @@ package org.oxycblt.auxio.detail.adapters
|
|||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import org.oxycblt.auxio.databinding.ItemArtistBinding
|
||||
import org.oxycblt.auxio.databinding.ItemGenreArtistBinding
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.bindArtistCounts
|
||||
import org.oxycblt.auxio.recycler.BaseViewHolder
|
||||
import org.oxycblt.auxio.recycler.ClickListener
|
||||
import org.oxycblt.auxio.recycler.DiffCallback
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.view.ViewGroup
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.oxycblt.auxio.databinding.ItemAlbumBinding
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.bindAlbumSongs
|
||||
import org.oxycblt.auxio.recycler.BaseViewHolder
|
||||
import org.oxycblt.auxio.recycler.ClickListener
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.view.ViewGroup
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.oxycblt.auxio.databinding.ItemArtistBinding
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.bindArtistCounts
|
||||
import org.oxycblt.auxio.recycler.BaseViewHolder
|
||||
import org.oxycblt.auxio.recycler.ClickListener
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ data class Song(
|
|||
|
||||
// Album
|
||||
data class Album(
|
||||
override val id: Long = -1,
|
||||
override val id: Long = Long.MIN_VALUE,
|
||||
override val name: String,
|
||||
val artistName: String,
|
||||
val coverUri: Uri = Uri.EMPTY,
|
||||
|
@ -47,7 +47,7 @@ data class Album(
|
|||
|
||||
// Artist
|
||||
data class Artist(
|
||||
override val id: Long = -1,
|
||||
override val id: Long = Long.MIN_VALUE,
|
||||
override var name: String,
|
||||
val givenGenres: MutableList<Genre> = mutableListOf()
|
||||
) : BaseModel() {
|
||||
|
@ -67,7 +67,7 @@ data class Artist(
|
|||
|
||||
// Genre
|
||||
data class Genre(
|
||||
override val id: Long = -1,
|
||||
override val id: Long = Long.MIN_VALUE,
|
||||
override var name: String,
|
||||
) : BaseModel() {
|
||||
val artists = mutableListOf<Artist>()
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package org.oxycblt.auxio.music
|
||||
|
||||
import android.content.ContentUris
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.provider.MediaStore
|
||||
import android.text.format.DateUtils
|
||||
|
@ -98,7 +97,11 @@ fun TextView.bindGenreCounts(genre: Genre) {
|
|||
// TODO: Add option to list all genres
|
||||
@BindingAdapter("artistGenre")
|
||||
fun TextView.bindArtistGenre(artist: Artist) {
|
||||
text = artist.genres[0].name
|
||||
text = if (artist.genres.isNotEmpty()) {
|
||||
artist.genres[0].name
|
||||
} else {
|
||||
context.getString(R.string.placeholder_genre)
|
||||
}
|
||||
}
|
||||
|
||||
// Get the artist counts
|
||||
|
|
|
@ -31,6 +31,7 @@ class SongAdapter(
|
|||
|
||||
override fun onBind(model: Song) {
|
||||
binding.song = model
|
||||
|
||||
binding.songName.requestLayout()
|
||||
binding.songInfo.requestLayout()
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
android:layout_marginStart="@dimen/margin_medium"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:onClick="@{() -> detailModel.navToParent()}"
|
||||
android:onClick="@{() -> detailModel.updateArtist(album.artist)}"
|
||||
android:text="@{album.artist.name}"
|
||||
android:textAppearance="?android:attr/textAppearanceListItem"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
|
|
Loading…
Reference in a new issue