I have a repository class with an asynchronous method returning User
wrapped into a LiveData
:
interface Repository {
fun getUser(): LiveData<User>
}
In a ViewModel's coruotine scope I want to wait for a result of getUser()
method and use an User
instance.
this is what, I am looking for:
private fun process() = viewModelScope.launch {
val user = repository.getUser().await()
// do something with a user instance
}
I could not find LiveData<>.await()
extension method, and any attempts to implement it.
So before doing it my self, I wonder maybe there is some better way?
All solutions that I have found were about making getUser()
a suspend
method, but what if I can not change Repository
?
You can know more about advanced coroutines with Kotlin Flow and LiveData and include the logical aspect of your code in a LiveData builder. Kotlin Coroutines 1. 2. 0 comes up with a cold stream called Flow. Kotlin Flow is used for carrying out asynchronous operations.
By combining Kotlin Coroutines Flow, LiveData and Data Binding you can perform asynchronous operations.
Use Kotlin to simplify my code by being more concise and focus on (isolated) minimal tasks. I’ll first use a simple ViewModel with some LiveData objects that the Activity will be able to observe. Here is how MainActivity uses it: I’m also okay in most cases with Google’s demo code on ViewModel:
To wait for a coroutine to finish, you can call Job.join. join is a suspending function, meaning that the coroutine calling it will be suspended until it is told to resume. At the point of suspension, the executing thread is released to any other available coroutines (that are sharing that thread or thread pool).
You should be able to create an await()
extension function using suspendCancellableCoroutine()
. This probably is not exactly correct, but something along these lines should work:
public suspend fun <T> LiveData<T>.await(): T {
return withContext(Dispatchers.Main.immediate) {
suspendCancellableCoroutine { continuation ->
val observer = object : Observer<T> {
override fun onChanged(value: T) {
removeObserver(this)
continuation.resume(value)
}
}
observeForever(observer)
continuation.invokeOnCancellation {
removeObserver(observer)
}
}
}
}
This should return the first value emitted by the LiveData
, without leaving an observer behind.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With