【问题标题】:What is better solution than await with async in coroutines?有什么比在协程中使用异步等待更好的解决方案?
【发布时间】:2022-11-04 22:18:07
【问题描述】:

我使用livedata 收集item 数据,在onClicked() 之后我从livedata 中获取这些数据。有什么更好的方法呢?

                lifecycleScope.launch {
                    lifecycleScope.async {
                        viewModel.fetchItem(args.workId)
                    }.await()
                    onClicked()
                }

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 方法

    fun fetchItem(id: Int) {
        viewModelScope.launch {
            _item.postAsyncValue { repository.getItem(id) }
        }
    }

【问题讨论】:

    标签: android kotlin asynchronous kotlin-coroutines android-livedata


    【解决方案1】:

    目前,我认为您的代码没有按照您的想法执行。 fetchItem 不是挂起函数。它启动一个协程并立即返回,而无需等待协程完成。因此,调用它的 async 协程也不会等待该结果。在这里使用async 毫无意义,因为代码几乎立即返回。

    我猜你想要完成的是等待postAsyncValue 完成设置新值。我不熟悉这个函数,但如果它是一个挂起函数,那么你应该这样构造你的代码。将fetchItem 设为挂起函数,直接调用另一个挂起函数。然后你可以在你的另一个协程中正常调用它,而不用将它包装在另一个协程中。

    suspend fun fetchItem(id: Int) {
        _item.postAsyncValue { repository.getItem(id) }
    }
    
    //...
    
    lifecycleScope.launch {
        viewModel.fetchItem(args.workId)
        onClicked()
    }
    

    如果这不正确,请添加postAsyncValue 的源代码并告诉我。


    关于您的字面问题,您可以使用withContext(Dispatchers.IO) { },而不是使用async,然后紧跟await,但只有在调用阻塞代码时才会这样做。当您使用并行性时,您只需要async,因此编译器会警告您,如果您在async { } 之后立即调用await(),您正在做一些愚蠢的事情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-05
      • 1970-01-01
      • 2012-03-31
      • 2013-07-21
      • 2020-01-02
      • 1970-01-01
      • 2016-07-24
      • 1970-01-01
      相关资源
      最近更新 更多