Eko Prasetyo
05/22/2022, 4:31 AM_state.value = _state.value.copy(...)
. Does something like this should be avoided or affecting performance?Ji Sungbin
05/22/2022, 5:39 AMMichael Paus
05/22/2022, 7:50 AMJi Sungbin
05/22/2022, 7:53 AMPaul Woitaschek
05/22/2022, 9:03 AMPaul Woitaschek
05/22/2022, 9:04 AMPaul Woitaschek
05/22/2022, 9:07 AMPaul Woitaschek
05/22/2022, 9:09 AMEko Prasetyo
05/22/2022, 10:03 AMdorche
05/22/2022, 11:57 AMEko Prasetyo
05/22/2022, 12:11 PMCasey Brooks
05/23/2022, 3:38 PM.copy()
-ing a data class is pretty negligible, overall. I’ve got a library, Ballast, where I’ve used this pattern with UI updates that emit very frequently, and the pattern itself has never caused me any noticeable performance issues, even in situations where I thought it might because the updates were emitting so quickly. Switching threads to handle those updates is what makes your app feel slow (especially when typing with Compose), for example updating the StateFlow like this:
fun updateText(textFieldValue: TextFieldValue) {
viewModelScope.launch(Dispatchers.Default) { // don't do this, keep it on Dispatchers.Main
_state.update { it.copy(text = textFieldValue) }
}
}
Another thing to watch out for is multiple coroutines updating the state concurrently. Any single update done with .update { }
will be thread-safe against race conditions, but the code you write can still be vulnerable to race conditions because coroutines are still concurrent, even on a single-threaded dispatcher. I have an example in the Ballast docs demonstrating the problem, as well as some strategies for protecting against it, which are all supported out-of-the-box in Ballast