【问题标题】:Can I instantiate a user object directly using MutableLiveData in Kotlin?我可以在 Kotlin 中使用 MutableLiveData 直接实例化用户对象吗?
【发布时间】:2020-04-04 08:41:30
【问题描述】:

文字A和代码A来自这个article

我很奇怪他们为什么不使用代码 B 或代码 C 来实例化用户对象。我觉得 Code B 和 Code C 非常简单明了。

顺便说一句,我没有测试过代码 B 和代码 C,但我认为它们是正确的。

文字A

使用 LiveData 时,您可能需要异步计算值。例如,您可能想要检索用户的偏好并将它们提供给您的 UI。在这些情况下,您可以使用 liveData 构建器函数调用挂起函数,将结果作为 LiveData 对象提供。 在下面的示例中,loadUser() 是在别处声明的挂起函数。使用 liveData builder 函数异步调用 loadUser(),然后使用 emit() 发出结果

代码 A

val user: LiveData<User> = liveData {
    val data = database.loadUser() // loadUser is a suspend function.
    emit(data)
}

代码 B

val user: LiveData<User> = MutableLiveData<User>(database.loadUser())

代码 C

val user = MutableLiveData<User>(database.loadUser())

【问题讨论】:

  • 你知道什么是挂起函数和协程吗?您不能使用代码 B 和代码 C,因为 loadUser 是挂起函数,但 liveData {...} 创建 CoroutineLiveData 在协程中通过挂起 lamda 运行
  • 因为这是suspend lambda,所以可以在里面使用其他的suspend函数

标签: android kotlin kotlin-coroutines android-ktx


【解决方案1】:

当您对该代码使用 B 或 C 方法时,您正在调用 MutableLiveData() 构造函数,这是一个普通的旧构造函数调用,这意味着它以阻塞方式同步执行。当您传入对它的调用时,例如database.loadUser(),该表达式将首先被求值(同样,阻塞和同步,在同一个线程上),然后将其结果传递给构造函数。

这样做的问题是,如果您在整个构造函数调用中都在主线程上,并且无论您传递给它什么,您都会在加载数据期间阻塞整个线程。

协程允许您通过使用挂起函数来释放当前线程。但是,您不能只是混合和匹配阻塞和挂起功能,因为那没有意义。相反,您必须在协程中调用挂起函数。

liveData 构建器函数允许您创建一个 LiveData 实例,并使用协程异步为其提供数据,并能够调用挂起函数,例如示例中的 loadUser() ,它可以是一个挂起函数。因此,创建这个LiveData 将是快速且非阻塞的,而您在该构建器中定义的协程可以异步执行,并在加载完成后使用emit()LiveData 中设置结果。

【讨论】:

    猜你喜欢
    • 2011-06-02
    • 1970-01-01
    • 1970-01-01
    • 2014-08-22
    • 1970-01-01
    • 2011-06-06
    • 2010-09-17
    • 2014-09-14
    • 1970-01-01
    相关资源
    最近更新 更多