Android Listadapter Submitlist Caveats

submitList and currentList concurrency issues

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 and submitApples cannot be override each other's execution, thus commitCallback shall always be called.
  • submitOranges and submitApples 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.

❤️ Is this article helpful?

Buy me a coffee ☕ or support my work via PayPal to keep this space 🖖 and ad-free.

Do send some 💖 to @d_luaz or share this article.

✨ By Desmond Lua

A dream boy who enjoys making apps, travelling and making youtube videos. Follow me on @d_luaz

👶 Apps I built

Travelopy - discover travel places in Malaysia, Singapore, Taiwan, Japan.