Add parent ViewHolder

Add an base ViewHolder class so that there isnt as much repeated code.
This commit is contained in:
OxygenCobalt 2020-09-27 11:13:24 -06:00
parent d99347722e
commit f866e77ee4
11 changed files with 55 additions and 135 deletions

View file

@ -33,9 +33,7 @@ TODO:
/other/
- Create inherited adapter/viewholder so I dont have to repeat as much code
- ? Condense detail fragments into a single fragment ?
- Make data items inherit a single class
- Condense artist/album recyclerview items into single item
- Remove binding adapters

View file

@ -3,9 +3,9 @@ package org.oxycblt.auxio.detail.adapters
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.databinding.ItemArtistAlbumBinding
import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.recycler.BaseViewHolder
import org.oxycblt.auxio.recycler.ClickListener
import org.oxycblt.auxio.recycler.DiffCallback
@ -26,26 +26,11 @@ class DetailAlbumAdapter(
// Generic ViewHolder for an album
inner class ViewHolder(
private val binding: ItemArtistAlbumBinding
) : RecyclerView.ViewHolder(binding.root) {
) : BaseViewHolder<Album>(binding, listener) {
init {
// Force the viewholder to *actually* be the screen width so ellipsizing can work.
binding.root.layoutParams = RecyclerView.LayoutParams(
RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT
)
}
// Bind the view w/new data
fun bind(album: Album) {
binding.album = album
binding.root.setOnClickListener {
listener.onClick(album)
}
// Force-update the layout so ellipsizing works.
override fun onBind(model: Album) {
binding.album = model
binding.albumName.requestLayout()
binding.executePendingBindings()
}
}
}

View file

@ -3,9 +3,9 @@ package org.oxycblt.auxio.detail.adapters
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.databinding.ItemGenreArtistBinding
import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.recycler.BaseViewHolder
import org.oxycblt.auxio.recycler.ClickListener
import org.oxycblt.auxio.recycler.DiffCallback
@ -26,26 +26,11 @@ class DetailArtistAdapter(
// Generic ViewHolder for an album
inner class ViewHolder(
private val binding: ItemGenreArtistBinding
) : RecyclerView.ViewHolder(binding.root) {
) : BaseViewHolder<Artist>(binding, listener) {
init {
// Force the viewholder to *actually* be the screen width so ellipsizing can work.
binding.root.layoutParams = RecyclerView.LayoutParams(
RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT
)
}
// Bind the view w/new data
fun bind(artist: Artist) {
binding.artist = artist
binding.root.setOnClickListener {
listener.onClick(artist)
}
// Force-update the layout so ellipsizing works.
binding.artistImage.requestLayout()
binding.executePendingBindings()
override fun onBind(model: Artist) {
binding.artist = model
binding.artistName.requestLayout()
}
}
}

View file

@ -3,9 +3,9 @@ package org.oxycblt.auxio.detail.adapters
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.databinding.ItemAlbumSongBinding
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.recycler.BaseViewHolder
import org.oxycblt.auxio.recycler.ClickListener
import org.oxycblt.auxio.recycler.DiffCallback
@ -26,26 +26,11 @@ class DetailSongAdapter(
// Generic ViewHolder for a song
inner class ViewHolder(
private val binding: ItemAlbumSongBinding
) : RecyclerView.ViewHolder(binding.root) {
) : BaseViewHolder<Song>(binding, listener) {
init {
// Force the viewholder to *actually* be the screen width so ellipsizing can work.
binding.root.layoutParams = RecyclerView.LayoutParams(
RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT
)
}
// Bind the view w/new data
fun bind(song: Song) {
binding.song = song
binding.root.setOnClickListener {
listener.onClick(song)
}
// Force-update the layout so ellipsizing works.
override fun onBind(model: Song) {
binding.song = model
binding.songName.requestLayout()
binding.executePendingBindings()
}
}
}

View file

@ -26,7 +26,7 @@ import org.oxycblt.auxio.theme.applyDivider
class LibraryFragment : Fragment() {
// FIXME: Temp value, remove when there are actual preferences
private val libraryMode = SHOW_GENRES
private val libraryMode = SHOW_ARTISTS
private val musicModel: MusicViewModel by activityViewModels()
private val libraryModel: LibraryViewModel by activityViewModels()

View file

@ -5,6 +5,7 @@ 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.recycler.BaseViewHolder
import org.oxycblt.auxio.recycler.ClickListener
class AlbumAdapter(
@ -24,29 +25,13 @@ class AlbumAdapter(
holder.bind(data[position])
}
// Generic ViewHolder for an album
inner class ViewHolder(
private val binding: ItemAlbumBinding
) : RecyclerView.ViewHolder(binding.root) {
) : BaseViewHolder<Album>(binding, listener) {
init {
// Force the viewholder to *actually* be the screen width so ellipsizing can work.
binding.root.layoutParams = RecyclerView.LayoutParams(
RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT
)
}
// Bind the view w/new data
fun bind(album: Album) {
binding.album = album
binding.root.setOnClickListener {
listener.onClick(album)
}
// Force-update the layout so ellipsizing works.
override fun onBind(model: Album) {
binding.album = model
binding.albumName.requestLayout()
binding.executePendingBindings()
}
}
}

View file

@ -5,6 +5,7 @@ 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.recycler.BaseViewHolder
import org.oxycblt.auxio.recycler.ClickListener
class ArtistAdapter(
@ -24,27 +25,13 @@ class ArtistAdapter(
holder.bind(data[position])
}
// Generic ViewHolder for an artist
inner class ViewHolder(
private val binding: ItemArtistBinding
) : RecyclerView.ViewHolder(binding.root) {
) : BaseViewHolder<Artist>(binding, listener) {
init {
// Force the viewholder to *actually* be the screen width so ellipsizing can work.
binding.root.layoutParams = RecyclerView.LayoutParams(
RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT
)
}
// Bind the view w/new data
fun bind(artist: Artist) {
binding.artist = artist
binding.root.setOnClickListener { listener.onClick(artist) }
// Force-update the layout so ellipsizing works.
override fun onBind(model: Artist) {
binding.artist = model
binding.artistName.requestLayout()
binding.executePendingBindings()
}
}
}

View file

@ -5,6 +5,7 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.databinding.ItemGenreBinding
import org.oxycblt.auxio.music.Genre
import org.oxycblt.auxio.recycler.BaseViewHolder
import org.oxycblt.auxio.recycler.ClickListener
class GenreAdapter(
@ -24,27 +25,13 @@ class GenreAdapter(
holder.bind(data[position])
}
// Generic ViewHolder for an artist
inner class ViewHolder(
private val binding: ItemGenreBinding
) : RecyclerView.ViewHolder(binding.root) {
) : BaseViewHolder<Genre>(binding, listener) {
init {
// Force the viewholder to *actually* be the screen width so ellipsizing can work.
binding.root.layoutParams = RecyclerView.LayoutParams(
RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT
)
}
// Bind the view w/new data
fun bind(genre: Genre) {
binding.genre = genre
binding.root.setOnClickListener { listener.onClick(genre) }
// Force-update the layout so ellipsizing works.
override fun onBind(model: Genre) {
binding.genre = model
binding.artistName.requestLayout()
binding.executePendingBindings()
}
}
}

View file

@ -1,6 +1,8 @@
package org.oxycblt.auxio.recycler
import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.R
import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.Artist
@ -10,7 +12,7 @@ import org.oxycblt.auxio.music.Song
// RecyclerView click listener
class ClickListener<T>(val onClick: (T) -> Unit)
// Song Diff callback
// Base Diff callback
class DiffCallback<T : BaseModel> : DiffUtil.ItemCallback<T>() {
override fun areContentsTheSame(oldItem: T, newItem: T): Boolean {
return oldItem.id == newItem.id
@ -21,6 +23,28 @@ class DiffCallback<T : BaseModel> : DiffUtil.ItemCallback<T>() {
}
}
// ViewHolder abstraction that automates some of the things that are common for all ViewHolders.
abstract class BaseViewHolder<T : BaseModel>(
private val baseBinding: ViewDataBinding,
protected val listener: ClickListener<T>
) : RecyclerView.ViewHolder(baseBinding.root) {
init {
baseBinding.root.layoutParams = RecyclerView.LayoutParams(
RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT
)
}
fun bind(model: T) {
baseBinding.root.setOnClickListener { listener.onClick(model) }
onBind(model)
baseBinding.executePendingBindings()
}
abstract fun onBind(model: T)
}
// Sorting modes
enum class SortMode(val iconRes: Int) {
// Icons for each mode are assigned to the enums themselves

View file

@ -5,6 +5,7 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.databinding.ItemSongBinding
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.recycler.BaseViewHolder
import org.oxycblt.auxio.recycler.ClickListener
class SongAdapter(
@ -24,31 +25,14 @@ class SongAdapter(
holder.bind(data[position])
}
// Generic ViewHolder for an album
inner class ViewHolder(
private val binding: ItemSongBinding
) : RecyclerView.ViewHolder(binding.root) {
) : BaseViewHolder<Song>(binding, listener) {
init {
// Force the viewholder to *actually* be the screen width so ellipsizing can work.
binding.root.layoutParams = RecyclerView.LayoutParams(
RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT
)
}
// Bind the view w/new data
fun bind(song: Song) {
binding.song = song
binding.root.setOnClickListener {
listener.onClick(song)
}
// Force-update the layouts so ellipsizing works.
override fun onBind(model: Song) {
binding.song = model
binding.songName.requestLayout()
binding.songInfo.requestLayout()
binding.executePendingBindings()
}
}
}