Created
November 7, 2018 08:25
-
-
Save jsaund/2d29c63da736d6699214604cddc4c43c to your computer and use it in GitHub Desktop.
Android RecyclerView example of creating an Async Diff Util with Coroutines
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
internal sealed class UpdateListOperation { | |
object Clear : UpdateListOperation() | |
data class Insert(val newList: List<*>) : UpdateListOperation() | |
} | |
private val updateActor = actor<UpdateListOperation>(UI, CONFLATED, parent = job) { | |
consumeEach { | |
if (!isActive) return@actor | |
val oldList = list | |
when (it) { | |
UpdateListOperation.Clear -> { | |
if (oldList != null) { | |
clear(oldList.size) | |
} | |
} | |
is UpdateListOperation.Insert -> { | |
if (oldList == null) { | |
insert(it.newList) | |
} else if (oldList != it.newList) { | |
val callback = | |
diffUtilCallback(oldList, it.newList as List<T>, itemCallback) | |
update(it.newList, callback) | |
} | |
} | |
} | |
} | |
} | |
fun update(newList: List<T>?) { | |
if (newList == null) { | |
updateActor.offer(UpdateListOperation.Clear) | |
} else { | |
updateActor.offer(UpdateListOperation.Insert(newList)) | |
} | |
} | |
private suspend fun clear(count: Int) { | |
withContext(UI) { | |
list = null | |
readOnlyList = emptyList() | |
listUpdateCallback.onRemoved(0, count) | |
} | |
} | |
private suspend fun insert(newList: List<*>) { | |
withContext(UI) { | |
list = newList as List<T> | |
readOnlyList = Collections.unmodifiableList(newList) | |
listUpdateCallback.onInserted(0, newList.size) | |
} | |
} | |
private suspend fun update(newList: List<*>, callback: DiffUtil.Callback) { | |
withContext(CommonPool) { | |
val result = DiffUtil.calculateDiff(callback) | |
if (!coroutineContext.isActive) return@withContext | |
latch(newList as List<T>, result) | |
} | |
} | |
private suspend fun latch(newList: List<T>, result: DiffUtil.DiffResult) { | |
withContext(UI) { | |
list = newList | |
readOnlyList = Collections.unmodifiableList(newList) | |
result.dispatchUpdatesTo(listUpdateCallback) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How can I use this code? Thx