Store references to items in DetailViewModel

Store references to the artist & album inside DetailViewModel to prevent an artist/album search on every re-creation.
This commit is contained in:
OxygenCobalt 2020-09-23 15:42:06 -06:00
parent f5d007267d
commit b80a3596b8
12 changed files with 115 additions and 68 deletions

View file

@ -0,0 +1,4 @@
package org.oxycblt.auxio
// RecyclerView click listener
class ClickListener<T>(val onClick: (T) -> Unit)

View file

@ -23,6 +23,3 @@ class MainActivity : AppCompatActivity() {
setContentView(R.layout.activity_main)
}
}
// RecyclerView click listener
class ClickListener<T>(val onClick: (T) -> Unit)

View file

@ -28,17 +28,22 @@ class AlbumDetailFragment : Fragment() {
): View? {
val binding = FragmentAlbumDetailBinding.inflate(inflater)
// I honestly don't want to turn of the any data classes into parcelables due to how
// many lists they store, so just pick up the artist id and find it from musicModel.
val musicModel: MusicViewModel by activityViewModels()
val album = musicModel.albums.value?.find { it.id == args.albumId }!!
// If DetailViewModel isn't already storing the album, get it from MusicViewModel
// using the ID given by the navigation arguments.
if (detailModel.currentAlbum == null) {
val musicModel: MusicViewModel by activityViewModels()
detailModel.currentAlbum = musicModel.albums.value!!.find {
it.id == args.albumId
}!!
}
binding.lifecycleOwner = this
binding.detailModel = detailModel
binding.album = album
binding.album = detailModel.currentAlbum
binding.songRecycler.adapter = DetailSongAdapter(
album.songs,
detailModel.currentAlbum!!.songs,
ClickListener {
Log.d(this::class.simpleName, it.name)
}
@ -46,16 +51,17 @@ class AlbumDetailFragment : Fragment() {
binding.songRecycler.applyDivider()
binding.songRecycler.setHasFixedSize(true)
// If the album was shown directly from LibraryFragment, then enable the ability
// to navigate to the artist from the album. Don't do this if the album was shown
// from ArtistDetailFragment, as you can just navigate up to see the parent artist.
if (args.isFromLibrary) {
// 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) {
findNavController().navigate(
AlbumDetailFragmentDirections.actionShowParentArtist(album.artist.id)
AlbumDetailFragmentDirections.actionShowParentArtist(
detailModel.currentAlbum!!.artist.id
)
)
detailModel.doneWithNavToParent()
@ -69,4 +75,4 @@ class AlbumDetailFragment : Fragment() {
return binding.root
}
}
}

View file

@ -28,20 +28,26 @@ class ArtistDetailFragment : Fragment() {
): View? {
val binding = FragmentArtistDetailBinding.inflate(inflater)
// I honestly don't want to turn of the any data classes into parcelables due to how
// many lists they store, so just pick up the artist id and find it from musicModel.
val musicModel: MusicViewModel by activityViewModels()
val artist = musicModel.artists.value?.find { it.id == args.artistId }!!
// If DetailViewModel isn't already storing the artist, get it from MusicViewModel
// using the ID given by the navigation arguments
if (detailModel.currentArtist == null) {
val musicModel: MusicViewModel by activityViewModels()
detailModel.currentArtist = musicModel.artists.value!!.find {
it.id == args.artistId
}!!
}
binding.lifecycleOwner = this
binding.artist = artist
binding.albumRecycler.adapter = DetailAlbumAdapter(
artist.albums,
val artistAdapter = DetailAlbumAdapter(
detailModel.currentArtist!!.albums,
ClickListener {
navToAlbum(it)
}
)
binding.lifecycleOwner = this
binding.artist = detailModel.currentArtist!!
binding.albumRecycler.adapter = artistAdapter
binding.albumRecycler.applyDivider()
binding.albumRecycler.setHasFixedSize(true)
@ -56,14 +62,22 @@ 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) {
detailModel.isAlreadyNavigating = true
findNavController().navigate(
ArtistDetailFragmentDirections.actionShowAlbum(album.id, false)
ArtistDetailFragmentDirections.actionShowAlbum(album.id)
)
}
}
}
}

View file

@ -3,6 +3,8 @@ package org.oxycblt.auxio.detail
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import org.oxycblt.auxio.music.models.Album
import org.oxycblt.auxio.music.models.Artist
class DetailViewModel : ViewModel() {
var isAlreadyNavigating = false
@ -10,6 +12,9 @@ class DetailViewModel : ViewModel() {
private val mNavToParentArtist = MutableLiveData<Boolean>()
val navToParentArtist: LiveData<Boolean> get() = mNavToParentArtist
var currentArtist: Artist? = null
var currentAlbum: Album? = null
fun navToParent() {
mNavToParentArtist.value = true
}
@ -17,4 +22,4 @@ class DetailViewModel : ViewModel() {
fun doneWithNavToParent() {
mNavToParentArtist.value = false
}
}
}

View file

@ -19,8 +19,7 @@ data class Artist(
}
fun finalizeGenre() {
// If the artist has more than one genre, pick the most "prominent" one.
// [Really just eliminate duplicates created from my hacky way of getting genres loaded but shhhh]
// If the artist has more than one genre, pick the most "Prominent" one.
genre = if (genres.size > 1) {
val groupGenres = genres.groupBy { it.name }

View file

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!--
<?xml version="1.0" encoding="utf-8"?>
<!--
Divider used by recyclerview header items
https://stackoverflow.com/a/61157571/14143986
-->
@ -12,4 +13,11 @@ https://stackoverflow.com/a/61157571/14143986
android:color="@color/divider_color" />
</shape>
</item>
<item>
<ripple
android:color="@color/selection_color"
android:radius="@dimen/divider_ripple_size">
</ripple>
</item>
</layer-list>

View file

@ -26,8 +26,7 @@
android:background="?android:attr/windowBackground"
android:elevation="@dimen/elevation_normal"
app:titleTextAppearance="@style/TextAppearance.Toolbar.Bold"
app:title="@string/title_library_fragment"
tools:titleTextColor="@color/blue" />
app:title="@string/title_library_fragment" />
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
@ -36,8 +35,7 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical">
android:animateLayoutChanges="true">
<ImageView
android:id="@+id/cover"
@ -56,11 +54,11 @@
style="@style/DetailHeader"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:layout_marginTop="@dimen/margin_medium"
android:layout_marginEnd="@dimen/margin_medium"
android:layout_marginStart="@dimen/margin_medium"
android:text="@{album.name}"
android:maxLines="1"
android:text="@{album.name}"
app:autoSizeMaxTextSize="@dimen/detail_header_size_max"
app:autoSizeMinTextSize="@dimen/generic_size_min"
app:autoSizeStepGranularity="@dimen/generic_size_increment"
@ -73,15 +71,15 @@
<TextView
android:id="@+id/artist_name"
android:clickable="true"
android:focusable="true"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_medium"
android:clickable="true"
android:focusable="true"
android:onClick="@{() -> detailModel.navToParent()}"
android:text="@{album.artist.name}"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorSecondary"
android:onClick="@{() -> detailModel.navToParent()}"
android:layout_marginStart="@dimen/margin_medium"
android:text="@{album.artist.name}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/album_name"
tools:text="Artist Name" />
@ -90,30 +88,29 @@
android:id="@+id/album_year"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorSecondary"
android:layout_marginStart="@dimen/margin_medium"
android:text="@{album.year != 0 ? String.valueOf(album.year) : @string/placeholder_no_date}"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorSecondary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/artist_name"
tools:text="2020" />
<TextView
android:id="@+id/header"
android:id="@+id/header_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/padding_medium"
android:background="@drawable/header_dividers"
android:fontFamily="@font/inter_bold"
android:paddingStart="@dimen/padding_medium"
android:paddingTop="@dimen/padding_small"
android:paddingEnd="@dimen/padding_small"
android:paddingBottom="@dimen/padding_small"
android:text="@string/label_songs"
android:textAppearance="@style/TextAppearance.MaterialComponents.Overline"
android:textSize="16sp"
android:fontFamily="@font/inter_bold"
android:layout_marginTop="@dimen/padding_medium"
android:paddingStart="@dimen/padding_medium"
android:paddingEnd="@dimen/padding_small"
android:paddingTop="@dimen/padding_small"
android:paddingBottom="@dimen/padding_small"
android:background="@drawable/header_dividers"
app:layout_constraintTop_toBottomOf="@+id/album_year"
tools:layout_editor_absoluteX="60dp" />
app:layout_constraintTop_toBottomOf="@+id/album_year" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/song_recycler"
@ -124,7 +121,7 @@
android:overScrollMode="never"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/header"
app:layout_constraintTop_toBottomOf="@+id/header_title"
tools:itemCount="4"
tools:listitem="@layout/item_album_song" />

View file

@ -22,8 +22,7 @@
android:background="?android:attr/windowBackground"
android:elevation="@dimen/elevation_normal"
app:titleTextAppearance="@style/TextAppearance.Toolbar.Bold"
app:title="@string/title_library_fragment"
tools:titleTextColor="@color/blue" />
app:title="@string/title_library_fragment" />
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
@ -91,21 +90,39 @@
tools:text="2 Albums, 20 Songs" />
<TextView
android:id="@+id/header"
android:id="@+id/header_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/margin_medium"
android:background="@drawable/header_dividers"
android:fontFamily="@font/inter_bold"
android:paddingStart="@dimen/padding_medium"
android:paddingTop="@dimen/padding_small"
android:paddingEnd="@dimen/padding_small"
android:paddingBottom="@dimen/padding_small"
android:text="@string/label_albums"
android:textAppearance="@style/TextAppearance.MaterialComponents.Overline"
android:textSize="16sp"
android:fontFamily="@font/inter_bold"
android:layout_marginTop="@dimen/padding_medium"
android:paddingStart="@dimen/padding_medium"
android:paddingEnd="@dimen/padding_small"
android:paddingTop="@dimen/padding_small"
android:paddingBottom="@dimen/padding_small"
android:background="@drawable/header_dividers"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/artist_counts" />
<!--
<ImageButton
android:id="@+id/sort_button"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_marginTop="@dimen/margin_medium"
android:background="@drawable/header_dividers"
android:contentDescription="@string/description_sort_button"
android:paddingStart="@dimen/padding_medium"
android:paddingTop="@dimen/padding_small"
android:paddingEnd="@dimen/margin_medium"
android:paddingBottom="@dimen/padding_small"
app:layout_constraintBottom_toTopOf="@+id/album_recycler"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/artist_counts" />
-->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/album_recycler"
android:layout_width="match_parent"
@ -115,7 +132,7 @@
android:overScrollMode="never"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/header"
app:layout_constraintTop_toBottomOf="@+id/header_title"
tools:itemCount="4"
tools:listitem="@layout/item_album" />

View file

@ -58,9 +58,6 @@
<argument
android:name="albumId"
app:argType="long" />
<argument
android:name="isFromLibrary"
app:argType="boolean" />
<action
android:id="@+id/action_show_parent_artist"
app:enterAnim="@anim/fragment_fade_enter"

View file

@ -24,5 +24,7 @@
<dimen name="generic_size_min">10sp</dimen>'
<dimen name="generic_size_increment">2sp</dimen>
<dimen name="divider_ripple_size">18dp</dimen>
<dimen name="elevation_normal">4dp</dimen>
</resources>

View file

@ -18,6 +18,7 @@
<string name="description_artist_image">Artist Cover for %s</string>
<string name="description_track_number">Track %s</string>
<string name="description_error">Error</string>
<string name="description_sort_button">Change Sorting Mode</string>
<string name="placeholder_genre">Unknown Genre</string>
<string name="placeholder_artist">Unknown Artist</string>