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/ /other/
- Create inherited adapter/viewholder so I dont have to repeat as much code
- ? Condense detail fragments into a single fragment ? - ? Condense detail fragments into a single fragment ?
- Make data items inherit a single class
- Condense artist/album recyclerview items into single item - Condense artist/album recyclerview items into single item
- Remove binding adapters - Remove binding adapters

View file

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

View file

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

View file

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

View file

@ -26,7 +26,7 @@ import org.oxycblt.auxio.theme.applyDivider
class LibraryFragment : Fragment() { class LibraryFragment : Fragment() {
// FIXME: Temp value, remove when there are actual preferences // 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 musicModel: MusicViewModel by activityViewModels()
private val libraryModel: LibraryViewModel by activityViewModels() private val libraryModel: LibraryViewModel by activityViewModels()

View file

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

View file

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

View file

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

View file

@ -1,6 +1,8 @@
package org.oxycblt.auxio.recycler package org.oxycblt.auxio.recycler
import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.R import org.oxycblt.auxio.R
import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Artist
@ -10,7 +12,7 @@ import org.oxycblt.auxio.music.Song
// RecyclerView click listener // RecyclerView click listener
class ClickListener<T>(val onClick: (T) -> Unit) class ClickListener<T>(val onClick: (T) -> Unit)
// Song Diff callback // Base Diff callback
class DiffCallback<T : BaseModel> : DiffUtil.ItemCallback<T>() { class DiffCallback<T : BaseModel> : DiffUtil.ItemCallback<T>() {
override fun areContentsTheSame(oldItem: T, newItem: T): Boolean { override fun areContentsTheSame(oldItem: T, newItem: T): Boolean {
return oldItem.id == newItem.id 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 // Sorting modes
enum class SortMode(val iconRes: Int) { enum class SortMode(val iconRes: Int) {
// Icons for each mode are assigned to the enums themselves // 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 androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.databinding.ItemSongBinding import org.oxycblt.auxio.databinding.ItemSongBinding
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.recycler.BaseViewHolder
import org.oxycblt.auxio.recycler.ClickListener import org.oxycblt.auxio.recycler.ClickListener
class SongAdapter( class SongAdapter(
@ -24,31 +25,14 @@ class SongAdapter(
holder.bind(data[position]) holder.bind(data[position])
} }
// Generic ViewHolder for an album
inner class ViewHolder( inner class ViewHolder(
private val binding: ItemSongBinding private val binding: ItemSongBinding
) : RecyclerView.ViewHolder(binding.root) { ) : BaseViewHolder<Song>(binding, listener) {
init { override fun onBind(model: Song) {
// Force the viewholder to *actually* be the screen width so ellipsizing can work. binding.song = model
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.
binding.songName.requestLayout() binding.songName.requestLayout()
binding.songInfo.requestLayout() binding.songInfo.requestLayout()
binding.executePendingBindings()
} }
} }
} }