Make shared ViewHolders used defined types

Make the shared ViewHolders use their respective types instead of BaseModel.
This commit is contained in:
OxygenCobalt 2020-10-03 19:42:16 -06:00
parent 2126b4f78f
commit 7abb888108
6 changed files with 66 additions and 67 deletions

View file

@ -24,7 +24,6 @@ import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.music.BaseModel import org.oxycblt.auxio.music.BaseModel
import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Genre
import org.oxycblt.auxio.music.MusicViewModel 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_ALBUMS
import org.oxycblt.auxio.theme.SHOW_ARTISTS import org.oxycblt.auxio.theme.SHOW_ARTISTS
import org.oxycblt.auxio.theme.SHOW_GENRES import org.oxycblt.auxio.theme.SHOW_GENRES
@ -44,14 +43,13 @@ class LibraryFragment : Fragment(), SearchView.OnQueryTextListener {
): View? { ): View? {
val binding = FragmentLibraryBinding.inflate(inflater) val binding = FragmentLibraryBinding.inflate(inflater)
val libraryAdapter = LibraryAdapter( val libraryAdapter = LibraryAdapter(libraryModel.showMode.value!!) {
libraryModel.showMode.value!!, navToItem(it)
ClickListener { navToItem(it) } }
)
val searchAdapter = SearchAdapter( val searchAdapter = SearchAdapter {
ClickListener { navToItem(it) } navToItem(it)
) }
// Toolbar setup // Toolbar setup
binding.libraryToolbar.overflowIcon = ContextCompat.getDrawable( binding.libraryToolbar.overflowIcon = ContextCompat.getDrawable(

View file

@ -23,7 +23,7 @@ class LibraryViewModel : ViewModel() {
val searchHasFocus: Boolean get() = mSearchHasFocus val searchHasFocus: Boolean get() = mSearchHasFocus
// TODO: Move these to prefs when they're added // TODO: Move these to prefs when they're added
private val mShowMode = MutableLiveData(SHOW_ALBUMS) private val mShowMode = MutableLiveData(SHOW_ARTISTS)
val showMode: LiveData<Int> get() = mShowMode val showMode: LiveData<Int> get() = mShowMode
private val mSortMode = MutableLiveData(SortMode.ALPHA_DOWN) private val mSortMode = MutableLiveData(SortMode.ALPHA_DOWN)

View file

@ -18,9 +18,15 @@ import org.oxycblt.auxio.theme.SHOW_GENRES
// the showmode given. It cannot display multiple types of viewholders *at once*. // the showmode given. It cannot display multiple types of viewholders *at once*.
class LibraryAdapter( class LibraryAdapter(
private val showMode: Int, private val showMode: Int,
val listener: ClickListener<BaseModel> private val doOnClick: (BaseModel) -> Unit
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
// Create separate listeners for each type, as ClickListeners can be converted
// to a type-specific form.
private val genreListener = ClickListener<Genre> { doOnClick(it) }
private val artistListener = ClickListener<Artist> { doOnClick(it) }
private val albumListener = ClickListener<Album> { doOnClick(it) }
private var data: List<BaseModel> private var data: List<BaseModel>
init { init {
@ -39,10 +45,10 @@ class LibraryAdapter(
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
// Return a different View Holder depending on the show type // Return a different View Holder depending on the show type
return when (showMode) { return when (showMode) {
SHOW_GENRES -> GenreViewHolder.from(parent.context, listener) SHOW_GENRES -> GenreViewHolder.from(parent.context, genreListener)
SHOW_ARTISTS -> ArtistViewHolder.from(parent.context, listener) SHOW_ARTISTS -> ArtistViewHolder.from(parent.context, artistListener)
SHOW_ALBUMS -> AlbumViewHolder.from(parent.context, listener) SHOW_ALBUMS -> AlbumViewHolder.from(parent.context, albumListener)
else -> ArtistViewHolder.from(parent.context, listener) else -> ArtistViewHolder.from(parent.context, artistListener)
} }
} }

View file

@ -18,8 +18,17 @@ import org.oxycblt.auxio.recycler.viewholders.HeaderViewHolder
import org.oxycblt.auxio.recycler.viewholders.SongViewHolder import org.oxycblt.auxio.recycler.viewholders.SongViewHolder
class SearchAdapter( class SearchAdapter(
private val listener: ClickListener<BaseModel> private val doOnClick: (BaseModel) -> Unit
) : ListAdapter<BaseModel, RecyclerView.ViewHolder>(DiffCallback<BaseModel>()) { ) : ListAdapter<BaseModel, RecyclerView.ViewHolder>(DiffCallback<BaseModel>()) {
// 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<Genre> { doOnClick(it) }
private val artistListener = ClickListener<Artist> { doOnClick(it) }
private val albumListener = ClickListener<Album> { doOnClick(it) }
private val songListener = ClickListener<Song> { doOnClick(it) }
override fun getItemViewType(position: Int): Int { override fun getItemViewType(position: Int): Int {
return when (getItem(position)) { return when (getItem(position)) {
is Genre -> GenreViewHolder.ITEM_TYPE is Genre -> GenreViewHolder.ITEM_TYPE
@ -32,10 +41,10 @@ class SearchAdapter(
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) { return when (viewType) {
GenreViewHolder.ITEM_TYPE -> GenreViewHolder.from(parent.context, listener) GenreViewHolder.ITEM_TYPE -> GenreViewHolder.from(parent.context, genreListener)
ArtistViewHolder.ITEM_TYPE -> ArtistViewHolder.from(parent.context, listener) ArtistViewHolder.ITEM_TYPE -> ArtistViewHolder.from(parent.context, artistListener)
AlbumViewHolder.ITEM_TYPE -> AlbumViewHolder.from(parent.context, listener) AlbumViewHolder.ITEM_TYPE -> AlbumViewHolder.from(parent.context, albumListener)
SongViewHolder.ITEM_TYPE -> SongViewHolder.from(parent.context, listener) SongViewHolder.ITEM_TYPE -> SongViewHolder.from(parent.context, songListener)
HeaderViewHolder.ITEM_TYPE -> HeaderViewHolder.from(parent.context) HeaderViewHolder.ITEM_TYPE -> HeaderViewHolder.from(parent.context)
else -> HeaderViewHolder.from(parent.context) else -> HeaderViewHolder.from(parent.context)
@ -44,13 +53,13 @@ class SearchAdapter(
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) { when (holder) {
is GenreViewHolder -> holder is GenreViewHolder -> holder.bind(getItem(position) as Genre)
is ArtistViewHolder -> holder is ArtistViewHolder -> holder.bind(getItem(position) as Artist)
is AlbumViewHolder -> holder is AlbumViewHolder -> holder.bind(getItem(position) as Album)
is SongViewHolder -> holder is SongViewHolder -> holder.bind(getItem(position) as Song)
is HeaderViewHolder -> holder is HeaderViewHolder -> holder.bind(getItem(position) as Header)
else -> return else -> return
}.bind(getItem(position)) }
} }
} }

View file

@ -9,7 +9,6 @@ import org.oxycblt.auxio.databinding.ItemHeaderBinding
import org.oxycblt.auxio.databinding.ItemSongBinding import org.oxycblt.auxio.databinding.ItemSongBinding
import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.music.BaseModel
import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Genre
import org.oxycblt.auxio.music.Header import org.oxycblt.auxio.music.Header
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
@ -19,19 +18,19 @@ import org.oxycblt.auxio.recycler.ClickListener
// FIXME: Mode these type signaturs to something sensible. // FIXME: Mode these type signaturs to something sensible.
class GenreViewHolder private constructor( class GenreViewHolder private constructor(
listener: ClickListener<BaseModel>, listener: ClickListener<Genre>,
private val binding: ItemGenreBinding private val binding: ItemGenreBinding
) : BaseViewHolder<BaseModel>(binding, listener) { ) : BaseViewHolder<Genre>(binding, listener) {
override fun onBind(model: BaseModel) { override fun onBind(model: Genre) {
binding.genre = model as Genre binding.genre = model
binding.genreName.requestLayout() binding.genreName.requestLayout()
} }
companion object { companion object {
const val ITEM_TYPE = 10 const val ITEM_TYPE = 10
fun from(context: Context, listener: ClickListener<BaseModel>): GenreViewHolder { fun from(context: Context, listener: ClickListener<Genre>): GenreViewHolder {
return GenreViewHolder( return GenreViewHolder(
ClickListener { listener.onClick(it) }, ClickListener { listener.onClick(it) },
ItemGenreBinding.inflate(LayoutInflater.from(context)) ItemGenreBinding.inflate(LayoutInflater.from(context))
@ -41,19 +40,19 @@ class GenreViewHolder private constructor(
} }
class ArtistViewHolder private constructor( class ArtistViewHolder private constructor(
listener: ClickListener<BaseModel>, listener: ClickListener<Artist>,
private val binding: ItemArtistBinding private val binding: ItemArtistBinding
) : BaseViewHolder<BaseModel>(binding, listener) { ) : BaseViewHolder<Artist>(binding, listener) {
override fun onBind(model: BaseModel) { override fun onBind(model: Artist) {
binding.artist = model as Artist binding.artist = model
binding.artistName.requestLayout() binding.artistName.requestLayout()
} }
companion object { companion object {
const val ITEM_TYPE = 11 const val ITEM_TYPE = 11
fun from(context: Context, listener: ClickListener<BaseModel>): ArtistViewHolder { fun from(context: Context, listener: ClickListener<Artist>): ArtistViewHolder {
return ArtistViewHolder( return ArtistViewHolder(
ClickListener { listener.onClick(it) }, ClickListener { listener.onClick(it) },
ItemArtistBinding.inflate(LayoutInflater.from(context)) ItemArtistBinding.inflate(LayoutInflater.from(context))
@ -63,19 +62,19 @@ class ArtistViewHolder private constructor(
} }
class AlbumViewHolder private constructor( class AlbumViewHolder private constructor(
listener: ClickListener<BaseModel>, listener: ClickListener<Album>,
private val binding: ItemAlbumBinding private val binding: ItemAlbumBinding
) : BaseViewHolder<BaseModel>(binding, listener) { ) : BaseViewHolder<Album>(binding, listener) {
override fun onBind(model: BaseModel) { override fun onBind(model: Album) {
binding.album = model as Album binding.album = model
binding.albumName.requestLayout() binding.albumName.requestLayout()
} }
companion object { companion object {
const val ITEM_TYPE = 12 const val ITEM_TYPE = 12
fun from(context: Context, listener: ClickListener<BaseModel>): AlbumViewHolder { fun from(context: Context, listener: ClickListener<Album>): AlbumViewHolder {
return AlbumViewHolder( return AlbumViewHolder(
listener, listener,
ItemAlbumBinding.inflate(LayoutInflater.from(context)) ItemAlbumBinding.inflate(LayoutInflater.from(context))
@ -85,12 +84,12 @@ class AlbumViewHolder private constructor(
} }
class SongViewHolder private constructor( class SongViewHolder private constructor(
listener: ClickListener<BaseModel>, listener: ClickListener<Song>,
private val binding: ItemSongBinding private val binding: ItemSongBinding
) : BaseViewHolder<BaseModel>(binding, listener) { ) : BaseViewHolder<Song>(binding, listener) {
override fun onBind(model: BaseModel) { override fun onBind(model: Song) {
binding.song = model as Song binding.song = model
binding.songName.requestLayout() binding.songName.requestLayout()
binding.songInfo.requestLayout() binding.songInfo.requestLayout()
@ -99,7 +98,7 @@ class SongViewHolder private constructor(
companion object { companion object {
const val ITEM_TYPE = 13 const val ITEM_TYPE = 13
fun from(context: Context, listener: ClickListener<BaseModel>): SongViewHolder { fun from(context: Context, listener: ClickListener<Song>): SongViewHolder {
return SongViewHolder( return SongViewHolder(
listener, listener,
ItemSongBinding.inflate(LayoutInflater.from(context)) ItemSongBinding.inflate(LayoutInflater.from(context))
@ -110,9 +109,9 @@ class SongViewHolder private constructor(
class HeaderViewHolder( class HeaderViewHolder(
private val binding: ItemHeaderBinding private val binding: ItemHeaderBinding
) : BaseViewHolder<BaseModel>(binding, null) { ) : BaseViewHolder<Header>(binding, null) {
override fun onBind(model: BaseModel) { override fun onBind(model: Header) {
binding.header = model as Header binding.header = model
} }
companion object { companion object {

View file

@ -7,33 +7,20 @@ import org.oxycblt.auxio.databinding.ItemSongBinding
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.recycler.ClickListener import org.oxycblt.auxio.recycler.ClickListener
import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder import org.oxycblt.auxio.recycler.viewholders.BaseViewHolder
import org.oxycblt.auxio.recycler.viewholders.SongViewHolder
class SongAdapter( class SongAdapter(
private val data: List<Song>, private val data: List<Song>,
private val listener: ClickListener<Song> private val listener: ClickListener<Song>
) : RecyclerView.Adapter<SongAdapter.ViewHolder>() { ) : RecyclerView.Adapter<SongViewHolder>() {
override fun getItemCount(): Int = data.size override fun getItemCount(): Int = data.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SongViewHolder {
return ViewHolder( return SongViewHolder.from(parent.context, listener)
ItemSongBinding.inflate(LayoutInflater.from(parent.context))
)
} }
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: SongViewHolder, position: Int) {
holder.bind(data[position]) holder.bind(data[position])
} }
inner class ViewHolder(
private val binding: ItemSongBinding
) : BaseViewHolder<Song>(binding, listener) {
override fun onBind(model: Song) {
binding.song = model
binding.songName.requestLayout()
binding.songInfo.requestLayout()
}
}
} }