接下来我们看看如何在 viewModelScope 里使用 LiveData。以前我们想在协程里做一些操作,并将结果反馈到 ViewModel 需要这么操作:
class MyViewModel : ViewModel {
private val _result = MutableLiveData()
val result: LiveData = _result
init {
viewModelScope.launch {
val computationResult = doComputation()
_result.value = computationResult
}
}
}
看看我们做了什么:
- 准备一个 ViewModel 私有的 MutableLiveData (MLD)
- 暴露一个不可变的 LiveData
- 启动协程,然后将其操作结果赋给 MLD
这个做法并不理想。在 LifeCycle 2.2.0 之后,同样的操作可以用更精简的方法来完成,也就是 LiveData 协程构造方法 (coroutine builder):
class MyViewModel {
val result = liveData {
emit(doComputation())
}
}
这个 liveData 协程构造方法提供了一个协程代码块,这个块就是 LiveData 的作用域,当 LiveData 被观察的时候,里面的操作就会被执行,当 LiveData 不再被使用时,里面的操作就会取消。而且该协程构造方法产生的是一个不可变的 LiveData,可以直接暴露给对应的视图使用。而 emit() 方法则用来更新 LiveData 的数据。
让我们来看另一个常见用例,比如当用户在 UI 中选中一些元素,然后将这些选中的内容显示出来。一个常见的做法是,把被选中的项目的 ID 保存在一个 MutableLiveData 里,然后运行 switchMap。现在在 switchMap 里,您也可以使用协程构造方法:
private val itemId = MutableLiveData()
val result = itemId.switchMap {
liveData { emit(fetchItem(it)) }
}
LiveData 协程构造方法还可以接收一个 Dispatcher 作为参数,这样您就可以将这个协程移至另一个线程。
liveData(Dispatchers.IO) {
}
最后,您还可以使用 emitSource() 方法从另一个 LiveData 获取更新的结果:
liveData(Dispatchers.IO) {
emit(LOADING_STRING)
emitSource(dataSource.fetchWeather())
}
接下来我们来看如何取消协程。绝大部分情况下,协程的取消操作是自动的,毕竟我们在对应的作用域里启动一个协程时ÿ