简体   繁体   English

在不阻塞主线程的情况下等待协程结果

[英]Waiting for coroutine result without blocking main thread

I've to update an item in a fragment based on the data returned from the.network call.我必须根据 .network 调用返回的数据更新片段中的项目。 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我不想阻塞主线程并以 ANR 结束,所以我采用了“回调”的方法,但是我想知道是否有一种方法可以在不依赖使用协程的回调机制的情况下等待 .network 调用的结果

Current implementation当前实施

MyFragment.kt我的片段.kt

fun updateButtonText() {
   handlerClass.getData {
      //received data from the server update the button text
   }
}

HandlerClass.kt处理器类.kt

fun getData(callback: (String) -> Unit) {
   scope.launch(Dispatchers.IO) {
      val data = mySuspendedNetworkcallMethod()

      callback.invoke(data)
   }
}

Desired Implementation:期望的实现:

MyFragment.kt我的片段.kt

fun updateButtonText() {
   val data = handlerClass.getData()
   button.text = data
}

HandlerClass.kt处理器类.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.据我所知,对于所需的演示实现,我必须使用 runBlocking{} 来调用挂起的方法,但是 runBlocking{} 将阻止调用线程 - 在这种情况下将是主线程,直到getData()返回数据。

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.我不想阻塞主线程,但仍然能够调用并等待挂起的方法来获取数据,然后更新按钮。

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:您可以在Fragment class 中使用lifecycleScope来启动生命周期感知协程,它将如下所示:

MyFragment.kt :我的片段.kt

fun updateButtonText() = lifecycleScope.launch {
   button.text = handlerClass.getData()
}

HandlerClass.kt :处理程序类.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.如果您使用MVVM方法,您应该考虑使用ViewModel及其viewModelScope扩展来启动协程。

For LifecycleScope , use androidx.lifecycle:lifecycle-runtime-ktx:2.4.0 or higher.对于LifecycleScope ,使用androidx.lifecycle:lifecycle-runtime-ktx:2.4.0或更高版本。

For ViewModelScope , use androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0 or higher.对于ViewModelScope ,使用androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0或更高版本。

Well recommended way is to use viewmodel and viewmodelscope for suspend functions.推荐的方法是将 viewmodel 和 viewmodelscope 用于挂起函数。

However in your situation, just use lifecyclescope但是在您的情况下,只需使用 lifecyclescope

    fun updateButtonText() {
       lifecycleScope.launch{
          val data = handlerClass.getData()
          button.text = data
       }
    }

https://developer.android.com/topic/libraries/architecture/coroutines https://developer.android.com/topic/libraries/architecture/coroutines

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM