文本A和代码A来自本文。
我很奇怪为什么他们不使用代码B或代码C来实例化用户对象。我认为代码B和代码C非常简单明了。
顺便说一句,我还没有测试代码B和代码C,但我认为它们是正确的。
文本A
使用LiveData时,可能需要异步计算值。例如,您可能想要检索用户的偏好并将其提供给您的UI。在这些情况下,您可以使用liveData构建器函数来调用suspend函数,将结果作为liveData对象。在下面的示例中,loadUser((是一个在其他地方声明的挂起函数。使用liveData构建器函数异步调用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方法处理此代码时,您正在调用MutableLiveData()
构造函数,这是一个简单的旧构造函数调用,意味着它是以阻塞的方式同步执行的。当您传入对它的调用(如database.loadUser()
(时,将首先对该表达式进行求值(同样,在同一线程上进行阻塞和同步(,然后将其结果传递给构造函数。
这样做的问题是,如果你在整个构造函数调用的主线程上,以及你传递给它的任何东西,那么在加载数据的过程中,你会阻塞整个线程。
Coroutines允许您通过使用挂起函数来释放当前线程。不过,您不能只是混合和匹配阻塞和挂起功能,因为这是没有意义的。相反,您必须在协程中调用挂起函数。
liveData
构造器函数允许您创建一个LiveData
实例,并使用协程异步地为其提供数据,并能够调用挂起函数,例如本例中的loadUser()
,它可以是一个挂起函数。因此,创建这个LiveData
将是快速且无阻塞的,而您在该构建器中定义的协同程序可以异步执行,并在加载完成后使用emit()
在LiveData
中设置结果。