I've to update an item in a fragment based on the data returned from the network call. I don't want to block the main thread and end up with ANR so I adopted the approach of "callbacks" however I wonder if there's a way to wait for the result from the network call without relying on the callback mechanism using coroutines
Current implementation
MyFragment.kt
fun updateButtonText() {
handlerClass.getData {
//received data from the server update the button text
}
}
HandlerClass.kt
fun getData(callback: (String) -> Unit) {
scope.launch(Dispatchers.IO) {
val data = mySuspendedNetworkcallMethod()
callback.invoke(data)
}
}
Desired Implementation:
MyFragment.kt
fun updateButtonText() {
val data = handlerClass.getData()
button.text = data
}
HandlerClass.kt
suspend fun getData() {
return mySuspendedNetworkcallMethod()
}
For the desired demo implementation, I understand, I'd have to use runBlocking{} to call a suspended method however runBlocking{} will block the calling thread - which in this case would be the Main Thread until getData()
returns the data.
I don't want to block the main thread but still be able to cal & wait for the suspended method to fetch the data and then update the button.
CodePudding user response:
Well recommended way is to use viewmodel and viewmodelscope for suspend functions.
However in your situation, just use lifecyclescope
fun updateButtonText() {
lifecycleScope.launch{
val data = handlerClass.getData()
button.text = data
}
}
https://developer.android.com/topic/libraries/architecture/coroutines
CodePudding user response:
Coroutines are designed to get rid of callbacks. You can use lifecycleScope
in the Fragment
class to launch a lifecycle-aware coroutine, it will look like the following:
MyFragment.kt:
fun updateButtonText() = lifecycleScope.launch {
button.text = handlerClass.getData()
}
HandlerClass.kt:
suspend fun getData() {
return mySuspendedNetworkcallMethod()
}
If you use MVVM
approach you should consider to use ViewModel
and it's viewModelScope
extension to launch coroutines.
For LifecycleScope
, use androidx.lifecycle:lifecycle-runtime-ktx:2.4.0
or higher.
For ViewModelScope
, use androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0
or higher.