Solution 1 :
Currently, I think your code is not doing what you think it does. fetchItem
is not a suspend function. It launches a coroutine and immediately returns without waiting for the coroutine to finish. So, your async
coroutine that calls it doesn’t wait for that result either. There’s no point in using async
at all here since the code returns almost immediately.
I’m guessing that what you’re trying to accomplish is wait for postAsyncValue
to finish setting that new value. To do this, you need to make fetchItem
a suspend function that waits for its work to be done.
I am not familiar with this postAsyncValue
, but my best guess is that it is a helper extension function on MutableLiveData that takes a suspend lambda, calls it, and then sets the value to the LiveData on the main thread. If this is the case, you should just do this instead so the function actually waits for the task to be done before returning:
suspend fun fetchItem(id: Int) = withContext(Dispatchers.Main) {
_item.value = repository.getItem(id) // assuming getItem is a suspend function
}
//...
lifecycleScope.launch {
viewModel.fetchItem(args.workId)
onClicked()
}
If this isn’t right, please add your source code for postAsyncValue
and let me know.
Regarding your literal question, instead of using async
followed immediately by await
, you can use withContext(Dispatchers.IO) { }
, but you would only do this if you are calling blocking code. You only need async
when you’re working with parallelism, so the compiler warns you that you’re doing something silly if you immediately call await()
after async { }
.
Problem :
I use livedata
that collect item
data, after it in onClicked()
I get this data from livedata. What could be better approach for this?
lifecycleScope.launch {
lifecycleScope.async {
viewModel.fetchItem(args.workId)
}.await()
onClicked()
}
variables in viewModel
val item = _item.immutable()
private val _item = MutableLiveData<ViewState<Item?>>()
[...]
// I wait here for data from first code than I collect it because item is liveData as above
private fun onClicked() {
val item = viewModel.item.value?.dataOrNull
[...]
fetchItem method
fun fetchItem(id: Int) {
viewModelScope.launch {
_item.postAsyncValue { repository.getItem(id) }
}
}