Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Example adapter implementation with DiffUtil
abstract class DiffUtilAdapter<D, VH : RecyclerView.ViewHolder> : RecyclerView.Adapter<VH>(), CoroutineScope {
override val coroutineContext = Dispatchers.Main.immediate
protected var dataset: List<D> = listOf()
private set
private val diffCallback by lazy(LazyThreadSafetyMode.NONE) { DiffCallback<D>() }
protected val detectMoves = true
private val updateActor = actor<List<D>>(capacity = Channel.CONFLATED) {
for (list in channel) internalUpdate(list)
}
protected abstract fun onUpdateFinished()
@MainThread
fun update (list: List<D>) {
updateActor.offer(list)
}
@MainThread
private suspend fun internalUpdate(list: List<D>) {
val (finalList, result) = withContext(Dispatchers.Default) {
val finalList = list.toList()
val result = DiffUtil.calculateDiff(diffCallback.apply { update(dataset, finalList) }, detectMoves)
Pair(finalList, result)
}
dataset = finalList
result.dispatchUpdatesTo(this@DiffUtilAdapter)
onUpdateFinished()
}
@MainThread
override fun getItemCount() = dataset.size
@MainThread
fun isEmpty() = dataset.isEmpty()
@MainThread
open fun getItem(position: Int) = dataset[position]
class DiffCallback<D> : DiffUtil.Callback() {
lateinit var oldList: List<D>
lateinit var newList: List<D>
fun update(oldList: List<D>, newList: List<D>) {
this.oldList = oldList
this.newList = newList
}
override fun getOldListSize() = oldList.size
override fun getNewListSize() = newList.size
override fun areContentsTheSame(oldItemPosition : Int, newItemPosition : Int) = true
override fun areItemsTheSame(oldItemPosition : Int, newItemPosition : Int) = oldList[oldItemPosition] == newList[newItemPosition]
}
}
@mochadwi

This comment has been minimized.

Copy link

@mochadwi mochadwi commented Aug 14, 2020

For simplicity as wrapper for DiffUtil adapter class use ListAdapter

But, if you wish for more control over adapter behavior, or to provide a specific base class should refer to AsyncListDiffer as stated in the official docs

Or use Paging library instead

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment