Skip to content

Instantly share code, notes, and snippets.

@GeoffreyMetais
Created October 10, 2018 13:38
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GeoffreyMetais/7c97389fed6b1674e4113d10bc656b92 to your computer and use it in GitHub Desktop.
Save GeoffreyMetais/7c97389fed6b1674e4113d10bc656b92 to your computer and use it in GitHub Desktop.
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
Copy link

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