Skip to content

Instantly share code, notes, and snippets.

@AliAzaz
Last active Sep 19, 2021
Embed
What would you like to do?
Generic RecyclerAdapter implementtion using DiffUtils
private lateinit var adapter: GenericListAdapter<ImagesInfo>
adapter = GenericListAdapter(R.layout.product_view) { item, position ->
viewModel.setSelectedProduct(item)
findNavController().navigate(ImageListFragmentDirections.actionImageListFragmentToImageDetailFragment())
}
//HOF callback
typealias OnItemClick<T> = (item: T, position: Int) -> Unit
// Adapter
class GenericListAdapter<T> internal constructor(
@IdRes private val layout: Int,
private val clickListener: OnItemClick<T>
) : RecyclerView.Adapter<GenericViewHolder<T>>() {
var productItems: ArrayList<T> = ArrayList()
set(value) {
field = value
val diffCallback =
GenericViewHolder.ChildViewDiffUtils(filteredProductItems, productItems)
val diffResult = DiffUtil.calculateDiff(diffCallback)
if (filteredProductItems.size > 0)
filteredProductItems.clear()
filteredProductItems.addAll(value)
diffResult.dispatchUpdatesTo(this)
}
private var filteredProductItems: ArrayList<T> = ArrayList()
set(value) {
field = value
val diffCallback =
GenericViewHolder.ChildViewDiffUtils(filteredProductItems, productItems)
val diffResult = DiffUtil.calculateDiff(diffCallback)
diffResult.dispatchUpdatesTo(this)
}
fun clearProductItem() {
filteredProductItems.clear()
}
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): GenericViewHolder<T> {
val layoutInflater = LayoutInflater.from(viewGroup.context)
val binding = DataBindingUtil.inflate<ViewDataBinding>(layoutInflater, i, viewGroup, false)
return GenericViewHolder(binding)
}
override fun onBindViewHolder(holder: GenericViewHolder<T>, i: Int) {
val item = filteredProductItems[i]
holder.bind(item)
holder.itemView.parentLayout.setOnClickListener {
clickListener(item, i)
}
}
override fun getItemCount(): Int = filteredProductItems.size
override fun getItemViewType(position: Int) = layout
}
// ViewHolder
class GenericViewHolder<T>(private val bi: ViewDataBinding) :
RecyclerView.ViewHolder(bi.root) {
fun bind(item: T) {
bi.apply {
bi.setVariable(BR.item, item)
bi.executePendingBindings()
}
}
class ChildViewDiffUtils<T>(
private val oldList: ArrayList<T>,
private val newList: ArrayList<T>
) :
DiffUtil.Callback() {
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition].toString() == newList[newItemPosition].toString()
}
override fun getOldListSize(): Int {
return oldList.size
}
override fun getNewListSize(): Int {
return newList.size
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition] == newList[newItemPosition]
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment