Home > Back-end >  Waiting for coroutine result without blocking main thread
Waiting for coroutine result without blocking main thread

Time:03-28

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.

  • Related