1

文本 A 和代码 A 来自这篇文章

我很奇怪为什么他们不使用代码 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())
4

1 回答 1

1

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

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

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

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

于 2020-04-04T10:10:10.587 回答