CoroutineLiveData
是 liveData
构造器创建出来的 LiveData
对象,它是 Jetpack 中为协程量身打造的 LiveData
版本,主要用来让我们在 LiveData
的作用域内,安全、方便地使用协程。
它的核心写法是这样的:
val data: LiveData<ResultType> = liveData {
val result = repository.loadData()
emit(result)
}
这个 liveData {}
块其实就是创建了一个 CoroutineLiveData
,它内部使用了 viewModelScope
或 LiveDataScope
来自动管理协程的生命周期。
需要异步请求但又想返回 LiveData 的时候:
比如从网络或数据库加载数据,但 View 层又只接受 LiveData
类型,这时候 liveData {}
非常方便。
不想自己手动管理 MediatorLiveData + Coroutine 的组合逻辑时:
MediatorLiveData
可以监听多个源,但当这些源的数据来自协程时,处理起来略显繁琐,而 CoroutineLiveData
更加优雅。
数据流只会有一个方向(比如一次性请求):
不适合频繁 emit 的场景,更适合像 suspend
函数那样发起请求、返回数据。
LiveData + postValue()
的方式最常见的写法是这样的:
val _data = MutableLiveData<Result>()
val data: LiveData<Result> = _data
fun loadData() {
viewModelScope.launch {
val result = repository.getData()
_data.postValue(result)
}
}
MutableLiveData
和一个外部 LiveData
;loadData()
要手动触发,适合响应事件式的数据(比如点击按钮加载);LiveData
的创建过程中就运行协程。CoroutineLiveData
(liveData {}
) 的方式val data: LiveData<Result> = liveData {
val result = repository.getData()
emit(result)
}
emitSource
来自动转发其他 LiveData
;suspend
函数,非常适合一次性加载数据(比如屏幕加载时拉取数据)。liveData {}
);MutableLiveData
);特性 | LiveData | MediatorLiveData | CoroutineLiveData (liveData{} ) |
---|---|---|---|
是否支持协程 | ❌ | ❌(需手动处理) | ✅ |
适合组合数据源 | ❌ | ✅ | ✅(通过多个 emitSource ) |
生命周期感知 | ✅ | ✅ | ✅ |
可读性 | ✅ | 易复杂 | ✅(特别是异步逻辑) |
场景 | 适合的方式 |
---|---|
ViewModel 里主动控制数据发射 | LiveData + postValue() |
想在 LiveData 创建过程中就运行协程逻辑 | liveData {} |
加载数据只需触发一次(如页面加载) | liveData {} |
需要多次触发请求或更新 | MutableLiveData + postValue() 更合适 |
数据源本身就是 Flow 或数据库 |
flow.asLiveData() 更现代化 |
liveData {}
默认运行在 Dispatchers.Main
,需要自己切换线程:
liveData(Dispatchers.IO) {
val result = repository.loadFromNetwork()
emit(result)
}
可以使用 emitSource
来转发一个已有的 LiveData
:
liveData {
emitSource(repository.getLocalCache())
}
不适合连续、频繁发射事件(比如倒计时) —— 这种更适合 Flow
+ asLiveData()
。
如果你是全协程架构,也可以这样使用:
val data: LiveData<Result> = repository.getDataFlow()
.asLiveData()
这样你就可以继续使用 LiveData
来绑定 UI,同时享受 Flow
的流式处理能力。