Issue
I have two suspend methods that I launch parallely inside a ViewModel:
init {
viewModelScope.launch(Dispatchers.Default) {
launch { loadTotalCirculation() }
launch { loadMarketPrice() }
}
}
private suspend fun loadTotalCirculation() {
val totalCirculation = bitcoinChartsRepository.getTotalCirculation(5, TimeUnit.HOURS)
_viewState.value = _viewState.value.copy(totalCirculation = chartViewEntityMapper(totalCirculation))
}
private suspend fun loadMarketPrice() {
val marketPrice = bitcoinChartsRepository.getMarketPrice(27, TimeUnit.DAYS)
_viewState.value = _viewState.value.copy(marketPrice = chartViewEntityMapper(marketPrice))
}
However, I would like to prevent the concurrent execution of the _viewState.value = _viewState.value.copy...
parts in both my methods. What's the best way to achieve this ?
Solution
There are several possibilities to synchronize parallel coroutines. Probably the easiest is to create a single thread context, similar to main thread or to use Mutex. Note this mutex is designed specifically for couroutines, it is not something from Java stdlib.
Single thread context:
val context = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
private suspend fun loadTotalCirculation() {
val totalCirculation = bitcoinChartsRepository.getTotalCirculation(5, TimeUnit.HOURS)
withContext (context) {
_viewState.value = _viewState.value.copy(totalCirculation = chartViewEntityMapper(totalCirculation))
}
}
private suspend fun loadMarketPrice() {
val marketPrice = bitcoinChartsRepository.getMarketPrice(27, TimeUnit.DAYS)
withContext (context) {
_viewState.value = _viewState.value.copy(marketPrice = chartViewEntityMapper(marketPrice))
}
}
Alternatively, instead of creating your own thread, you can reuse the main thread by: withContext(Dispatchers.Main)
.
Mutex:
val mutex = Mutex()
private suspend fun loadTotalCirculation() {
val totalCirculation = bitcoinChartsRepository.getTotalCirculation(5, TimeUnit.HOURS)
mutex.withLock {
_viewState.value = _viewState.value.copy(totalCirculation = chartViewEntityMapper(totalCirculation))
}
}
private suspend fun loadMarketPrice() {
val marketPrice = bitcoinChartsRepository.getMarketPrice(27, TimeUnit.DAYS)
mutex.withLock {
_viewState.value = _viewState.value.copy(marketPrice = chartViewEntityMapper(marketPrice))
}
}
Using a main thread or mutex is probably preferred, because if we create our own thread, we need to make sure to properly stop/close it when we won't need it anymore.
You can read more in this article from the official docs: https://kotlinlang.org/docs/shared-mutable-state-and-concurrency.html
Answered By - broot
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.