I have the following code which has a race condition. I try to find an item in a list and set its loading property. But if onLoaded("A")
and onLoaded("B")
are called multiple times from different threads. I always lose the data of the first call if it doesn't complete before second starts.
How can I make this work? Is using Mutex should be the correct approach?
val list = MutableLiveData<List<Model>>() // assume this is initialized with ["Model(false, "A"), Model(false, "B")]
data class Model(
val loaded: Boolean,
val item: String,
)
fun onLoaded(item: String) = viewModelScope.launch {
val currList = list.value ?: return@launch
withContext(Dispatchers.Default) {
val updated = currList.find { it.item == item }?.copy(loaded = true)
val mutable = currList.toMutableList()
updated?.let {
val index = mutable.indexOf(it)
mutable[index] = it
}
list.postValue(mutable.toList())
}
}
onLoaded("A")
onLoaded("B")
expected: ["Model(true, "A"), Model(true, "B")]
actual: ["Model(false, "A"), Model(true, "B")]