From 7abb8881080f2d85707a081dc3533e0bb783161b Mon Sep 17 00:00:00 2001 From: OxygenCobalt Date: Sat, 3 Oct 2020 19:42:16 -0600 Subject: [PATCH] Make shared ViewHolders used defined types Make the shared ViewHolders use their respective types instead of BaseModel. --- .../oxycblt/auxio/library/LibraryFragment.kt | 14 +++--- .../oxycblt/auxio/library/LibraryViewModel.kt | 2 +- .../auxio/library/recycler/LibraryAdapter.kt | 16 +++++-- .../auxio/library/recycler/SearchAdapter.kt | 31 +++++++----- .../recycler/viewholders/ModelHolders.kt | 47 +++++++++---------- .../org/oxycblt/auxio/songs/SongAdapter.kt | 23 ++------- 6 files changed, 66 insertions(+), 67 deletions(-) diff --git a/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt b/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt index 7c2de83dc..3a80352b7 100644 --- a/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt @@ -24,7 +24,6 @@ import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.BaseModel import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.MusicViewModel -import org.oxycblt.auxio.recycler.ClickListener import org.oxycblt.auxio.theme.SHOW_ALBUMS import org.oxycblt.auxio.theme.SHOW_ARTISTS import org.oxycblt.auxio.theme.SHOW_GENRES @@ -44,14 +43,13 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener { ): View? { val binding = FragmentLibraryBinding.inflate(inflater) - val libraryAdapter = LibraryAdapter( - libraryModel.showMode.value!!, - ClickListener { navToItem(it) } - ) + val libraryAdapter = LibraryAdapter(libraryModel.showMode.value!!) { + navToItem(it) + } - val searchAdapter = SearchAdapter( - ClickListener { navToItem(it) } - ) + val searchAdapter = SearchAdapter { + navToItem(it) + } // Toolbar setup binding.libraryToolbar.overflowIcon = ContextCompat.getDrawable( diff --git a/app/src/main/java/org/oxycblt/auxio/library/LibraryViewModel.kt b/app/src/main/java/org/oxycblt/auxio/library/LibraryViewModel.kt index 0e20d4562..27dbaace3 100644 --- a/app/src/main/java/org/oxycblt/auxio/library/LibraryViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/library/LibraryViewModel.kt @@ -23,7 +23,7 @@ class LibraryViewModel : ViewModel() { val searchHasFocus: Boolean get() = mSearchHasFocus // TODO: Move these to prefs when they're added - private val mShowMode = MutableLiveData(SHOW_ALBUMS) + private val mShowMode = MutableLiveData(SHOW_ARTISTS) val showMode: LiveData get() = mShowMode private val mSortMode = MutableLiveData(SortMode.ALPHA_DOWN) diff --git a/app/src/main/java/org/oxycblt/auxio/library/recycler/LibraryAdapter.kt b/app/src/main/java/org/oxycblt/auxio/library/recycler/LibraryAdapter.kt index c229ab67b..92d9e17a9 100644 --- a/app/src/main/java/org/oxycblt/auxio/library/recycler/LibraryAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/library/recycler/LibraryAdapter.kt @@ -18,9 +18,15 @@ import org.oxycblt.auxio.theme.SHOW_GENRES // the showmode given. It cannot display multiple types of viewholders *at once*. class LibraryAdapter( private val showMode: Int, - val listener: ClickListener + private val doOnClick: (BaseModel) -> Unit ) : RecyclerView.Adapter() { + // Create separate listeners for each type, as ClickListeners can be converted + // to a type-specific form. + private val genreListener = ClickListener { doOnClick(it) } + private val artistListener = ClickListener { doOnClick(it) } + private val albumListener = ClickListener { doOnClick(it) } + private var data: List init { @@ -39,10 +45,10 @@ class LibraryAdapter( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { // Return a different View Holder depending on the show type return when (showMode) { - SHOW_GENRES -> GenreViewHolder.from(parent.context, listener) - SHOW_ARTISTS -> ArtistViewHolder.from(parent.context, listener) - SHOW_ALBUMS -> AlbumViewHolder.from(parent.context, listener) - else -> ArtistViewHolder.from(parent.context, listener) + SHOW_GENRES -> GenreViewHolder.from(parent.context, genreListener) + SHOW_ARTISTS -> ArtistViewHolder.from(parent.context, artistListener) + SHOW_ALBUMS -> AlbumViewHolder.from(parent.context, albumListener) + else -> ArtistViewHolder.from(parent.context, artistListener) } } diff --git a/app/src/main/java/org/oxycblt/auxio/library/recycler/SearchAdapter.kt b/app/src/main/java/org/oxycblt/auxio/library/recycler/SearchAdapter.kt index cf6dbbe96..ef0b72833 100644 --- a/app/src/main/java/org/oxycblt/auxio/library/recycler/SearchAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/library/recycler/SearchAdapter.kt @@ -18,8 +18,17 @@ import org.oxycblt.auxio.recycler.viewholders.HeaderViewHolder import org.oxycblt.auxio.recycler.viewholders.SongViewHolder class SearchAdapter( - private val listener: ClickListener + private val doOnClick: (BaseModel) -> Unit ) : ListAdapter(DiffCallback()) { + + // Create separate listeners for each type, as a BaseModel ClickListener cant be + // casted to a ClickListener of a class that inherits BaseModel. + // FIXME: Maybe theres a way for this to be improved? + private val genreListener = ClickListener { doOnClick(it) } + private val artistListener = ClickListener { doOnClick(it) } + private val albumListener = ClickListener { doOnClick(it) } + private val songListener = ClickListener { doOnClick(it) } + override fun getItemViewType(position: Int): Int { return when (getItem(position)) { is Genre -> GenreViewHolder.ITEM_TYPE @@ -32,10 +41,10 @@ class SearchAdapter( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { return when (viewType) { - GenreViewHolder.ITEM_TYPE -> GenreViewHolder.from(parent.context, listener) - ArtistViewHolder.ITEM_TYPE -> ArtistViewHolder.from(parent.context, listener) - AlbumViewHolder.ITEM_TYPE -> AlbumViewHolder.from(parent.context, listener) - SongViewHolder.ITEM_TYPE -> SongViewHolder.from(parent.context, listener) + GenreViewHolder.ITEM_TYPE -> GenreViewHolder.from(parent.context, genreListener) + ArtistViewHolder.ITEM_TYPE -> ArtistViewHolder.from(parent.context, artistListener) + AlbumViewHolder.ITEM_TYPE -> AlbumViewHolder.from(parent.context, albumListener) + SongViewHolder.ITEM_TYPE -> SongViewHolder.from(parent.context, songListener) HeaderViewHolder.ITEM_TYPE -> HeaderViewHolder.from(parent.context) else -> HeaderViewHolder.from(parent.context) @@ -44,13 +53,13 @@ class SearchAdapter( override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { when (holder) { - is GenreViewHolder -> holder - is ArtistViewHolder -> holder - is AlbumViewHolder -> holder - is SongViewHolder -> holder - is HeaderViewHolder -> holder + is GenreViewHolder -> holder.bind(getItem(position) as Genre) + is ArtistViewHolder -> holder.bind(getItem(position) as Artist) + is AlbumViewHolder -> holder.bind(getItem(position) as Album) + is SongViewHolder -> holder.bind(getItem(position) as Song) + is HeaderViewHolder -> holder.bind(getItem(position) as Header) else -> return - }.bind(getItem(position)) + } } } diff --git a/app/src/main/java/org/oxycblt/auxio/recycler/viewholders/ModelHolders.kt b/app/src/main/java/org/oxycblt/auxio/recycler/viewholders/ModelHolders.kt index cf5fa7c96..8421711db 100644 --- a/app/src/main/java/org/oxycblt/auxio/recycler/viewholders/ModelHolders.kt +++ b/app/src/main/java/org/oxycblt/auxio/recycler/viewholders/ModelHolders.kt @@ -9,7 +9,6 @@ import org.oxycblt.auxio.databinding.ItemHeaderBinding import org.oxycblt.auxio.databinding.ItemSongBinding import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Artist -import org.oxycblt.auxio.music.BaseModel import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Header import org.oxycblt.auxio.music.Song @@ -19,19 +18,19 @@ import org.oxycblt.auxio.recycler.ClickListener // FIXME: Mode these type signaturs to something sensible. class GenreViewHolder private constructor( - listener: ClickListener, + listener: ClickListener, private val binding: ItemGenreBinding -) : BaseViewHolder(binding, listener) { +) : BaseViewHolder(binding, listener) { - override fun onBind(model: BaseModel) { - binding.genre = model as Genre + override fun onBind(model: Genre) { + binding.genre = model binding.genreName.requestLayout() } companion object { const val ITEM_TYPE = 10 - fun from(context: Context, listener: ClickListener): GenreViewHolder { + fun from(context: Context, listener: ClickListener): GenreViewHolder { return GenreViewHolder( ClickListener { listener.onClick(it) }, ItemGenreBinding.inflate(LayoutInflater.from(context)) @@ -41,19 +40,19 @@ class GenreViewHolder private constructor( } class ArtistViewHolder private constructor( - listener: ClickListener, + listener: ClickListener, private val binding: ItemArtistBinding -) : BaseViewHolder(binding, listener) { +) : BaseViewHolder(binding, listener) { - override fun onBind(model: BaseModel) { - binding.artist = model as Artist + override fun onBind(model: Artist) { + binding.artist = model binding.artistName.requestLayout() } companion object { const val ITEM_TYPE = 11 - fun from(context: Context, listener: ClickListener): ArtistViewHolder { + fun from(context: Context, listener: ClickListener): ArtistViewHolder { return ArtistViewHolder( ClickListener { listener.onClick(it) }, ItemArtistBinding.inflate(LayoutInflater.from(context)) @@ -63,19 +62,19 @@ class ArtistViewHolder private constructor( } class AlbumViewHolder private constructor( - listener: ClickListener, + listener: ClickListener, private val binding: ItemAlbumBinding -) : BaseViewHolder(binding, listener) { +) : BaseViewHolder(binding, listener) { - override fun onBind(model: BaseModel) { - binding.album = model as Album + override fun onBind(model: Album) { + binding.album = model binding.albumName.requestLayout() } companion object { const val ITEM_TYPE = 12 - fun from(context: Context, listener: ClickListener): AlbumViewHolder { + fun from(context: Context, listener: ClickListener): AlbumViewHolder { return AlbumViewHolder( listener, ItemAlbumBinding.inflate(LayoutInflater.from(context)) @@ -85,12 +84,12 @@ class AlbumViewHolder private constructor( } class SongViewHolder private constructor( - listener: ClickListener, + listener: ClickListener, private val binding: ItemSongBinding -) : BaseViewHolder(binding, listener) { +) : BaseViewHolder(binding, listener) { - override fun onBind(model: BaseModel) { - binding.song = model as Song + override fun onBind(model: Song) { + binding.song = model binding.songName.requestLayout() binding.songInfo.requestLayout() @@ -99,7 +98,7 @@ class SongViewHolder private constructor( companion object { const val ITEM_TYPE = 13 - fun from(context: Context, listener: ClickListener): SongViewHolder { + fun from(context: Context, listener: ClickListener): SongViewHolder { return SongViewHolder( listener, ItemSongBinding.inflate(LayoutInflater.from(context)) @@ -110,9 +109,9 @@ class SongViewHolder private constructor( class HeaderViewHolder( private val binding: ItemHeaderBinding -) : BaseViewHolder(binding, null) { - override fun onBind(model: BaseModel) { - binding.header = model as Header +) : BaseViewHolder
(binding, null) { + override fun onBind(model: Header) { + binding.header = model } companion object { diff --git a/app/src/main/java/org/oxycblt/auxio/songs/SongAdapter.kt b/app/src/main/java/org/oxycblt/auxio/songs/SongAdapter.kt index e56bfbb44..8f112d32b 100644 --- a/app/src/main/java/org/oxycblt/auxio/songs/SongAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/songs/SongAdapter.kt @@ -7,33 +7,20 @@ import org.oxycblt.auxio.databinding.ItemSongBinding import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.recycler.ClickListener import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder +import org.oxycblt.auxio.recycler.viewholders.SongViewHolder class SongAdapter( private val data: List, private val listener: ClickListener -) : RecyclerView.Adapter() { +) : RecyclerView.Adapter() { override fun getItemCount(): Int = data.size - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - return ViewHolder( - ItemSongBinding.inflate(LayoutInflater.from(parent.context)) - ) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SongViewHolder { + return SongViewHolder.from(parent.context, listener) } - override fun onBindViewHolder(holder: ViewHolder, position: Int) { + override fun onBindViewHolder(holder: SongViewHolder, position: Int) { holder.bind(data[position]) } - - inner class ViewHolder( - private val binding: ItemSongBinding - ) : BaseViewHolder(binding, listener) { - - override fun onBind(model: Song) { - binding.song = model - - binding.songName.requestLayout() - binding.songInfo.requestLayout() - } - } }