【问题标题】:How can I return a value to my ViewModel from CoroutineScope?如何从 CoroutineScope 向我的 ViewModel 返回值?
【发布时间】:2021-10-18 13:37:27
【问题描述】:

我的 Activity 想要使用 Room 在我的数据库中插入一个新元素,因此该 Activity 将此任务委托给传递 Entity 对象的 ViewModel 类。活动希望返回由数据库自动生成的 id 的值,以便可以实时更新对象。 因此,ViewModel 类希望在 IO 池线程上启动一个协程,该协程使用返回新 id 值的 insert Dao 方法。 最后,我的问题是:如何将协程中的值返回给 ViewModel 方法?

这是我在 ViewModel 类中的代码:

//return autogenerated id
fun insert(fiscalcode: Fiscalcode): Int {
    CoroutineScope(Dispatchers.IO).launch {
        db.fiscalcodeDao().insert(fiscalcode)
        //return autogenerated id
    }
}

【问题讨论】:

  • 你在用房间吗?如果是,你不需要给不同的调度员,它就可以工作
  • 如果 insert() 方法返回新 ID,那么您的 Activity 应该从 ViewModel 观察 LiveData<SomeState>,因此 VM 将 _someState.postValue(YourState(id)) 并且观察它的 Activity 会对其做出反应,如所述in the official documentation
  • 改用viewModelScope.async { ... } 并从lifecycleScope.launch { ... } 块内的活动中调用它。或者只是让您的 insert 函数暂停并从您的活动中调用它 lifecycleScope.launch { ... } 块。

标签: android kotlin android-room kotlin-coroutines


【解决方案1】:

不好的做法,但根据您的问题,如果您想返回,您可以使用 相同的运行阻塞

val id = runBlocking {
   db.fiscalcodeDao().insert(fiscalcode)
}

【讨论】:

    【解决方案2】:

    你不能混合悬浮世界和非悬浮世界。 您可以在视图模型中创建一个变量。

    val _rowId = MutableStateFlow<Int?>(null)
    val rowId: StateFlow<Int>
        get() = _rowId
    
    fun insert(fiscalcode: Fiscalcode): Int {
        CoroutineScope(Dispatchers.IO).launch {
           _rowId.value = db.fiscalcodeDao().insert(fiscalcode)
        }
    }
    

    你可以在你的活动中收集这个rowId Flow。

    lifecycleScope.launch {
        viewModel.rowId
                 .flowWithLifecycle(this, Lifecycle.State.STARTED)
                 .collect { rowId -> ... }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-04-10
      • 1970-01-01
      • 2021-11-27
      • 2021-03-30
      • 1970-01-01
      • 2021-11-03
      • 1970-01-01
      • 2021-05-29
      • 1970-01-01
      相关资源
      最近更新 更多