When using ListAdapter, ListAdapter.submitList
actually launch a background process to perform comparison before updating the actual ListAdapter.currentList
. If you rely on currentList
to perform update (e.g. check if an item exist or not before perform actual action), you need to make sure you get the latest currentList
.
Option 1: commitCallback
adapter.submitList(items) { // this is the callback after the background task is completed // currentList should be latest}
The commit callback can be used to know when the List is committed, but note that it may not be executed. If List B is submitted immediately after List A, and is committed directly, the callback associated with List A will not be run. - Source
As you can see, if you call submitList
immediately after submitList
, the callback might not be called.
Option 2: Mutex
I use Kotlin coroutines Mutex to make sure submitList should only be called after the prior update is committed.
In the following example, I have a fruit ListAdapter. Oranges will always list/appear before Apples (so I check currentList, prepend if orange, append if apple)
class FruitAdapter : ListAdapter<Fruit, LocalAdapter.ViewHolder>(DiffCallback()) { private val mutex = Mutex() suspend fun submitOranges(items: List<Fruit>) { mutex.lock() // clone list val newItems = currentList.toMutableList() // prepend to make sure oranges always appear first newItems.addAll(0, items) submitList(newItems) { mutex.unlock() } } suspend fun submitApples(items: List<Fruit>) { mutex.lock() // clone list val newItems = currentList.toMutableList() // append to make sure apples always appear last newItems.addAll(items) submitList(newItems) { mutex.unlock() } }}
With the mutex lock
submitOranges
andsubmitApples
cannot be override each other's execution, thuscommitCallback
shall always be called.submitOranges
andsubmitApples
shall always have access to the latest currentList
NOTE: If for some unepexted circumstances commitCallback
is not called, then both methods shall be permanently locked.
With this implementaion, you should not call submitList
directly, else it shall make the mutex implementation useless.
Use Mutex instead of ReentrantLock, as Mutex perform lock even when executed on the same thread.