Ten*_*r04 7 android kotlin android-room kotlin-coroutines kotlin-coroutines-flow
我有一个使用三个 LiveData 源的 MediatorLiveData。当它们中的任何一个发出一个新值并且我至少有一个值时,我使用这三个值来生成 UI 的输出。
其中两个来源是关于如何对列表进行排序和过滤的用户设置,第三个是从 Room 数据库 Flow 中提取的列表数据。
它看起来像这样:
val thingsLiveData: LiveData<List<Thing>> = object: MediatorLiveData<List<Thing>>() {
var isSettingA: Boolean = true
var settingB: MySortingEnum = MySortingEnum.Alphabetical
var data: List<Thing>? = null
init {
addSource(myRepo.thingsFlow.asLiveData()) {
data = it
dataToValue()
}
addSource(settingALiveData) {
isSettingA= it
dataToValue()
}
addSource(settingBLiveData) {
settingB= it
dataToValue()
}
}
private fun dataToValue() {
data?.let { data ->
viewModelScope.launch {
val uiList = withContext(Dispatchers.Default) {
produceUiList(data, isSettingA, settingB)
}
value = listItems
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我正在寻找一种干净的方法将其转换为 SharedFlow,最好没有任何@ExperimentalCoroutinesApi
. 我遇到的唯一 SharedFlow 构建器函数是callbackFlow
,它不适用。您是否打算flow { ... }.asSharedFlow(...)
在大多数情况下使用,如果是这样,这里会是什么样子?
这两个设置 LiveData 我还计划迁移到流。
可以使用 组合源流combine()
,这会创建一个冷流,在收集时,将开始从其源流收集,该源流可能是热的,也可能是冷的。
我原本以为我一定错过了一些东西,应该有某种方法可以直接将热流组合成组合热流。但我意识到,操作员应该只返回冷流,并让您自行将其转换回热流(如果您需要的话),这是有道理的。
在很多情况下,比如我的,把它放冷就完全没问题了。我只从 UI 中的一个位置收集此 Flow,因此仅在收集时才开始组合源并不重要。源热流并不关心当前是否有东西正在收集它们......它们只是继续发射。
如果我从多个地方或多次收集此流,那么shareIn
在组合流上使用它以使其热可能是有意义的,这将避免组合源的冗余工作。潜在的缺点是,即使没有收集任何数据,它也会合并这些来源,这将是浪费工作。
val thingsFlow: Flow<List<Thing>> = combine(
myRepo.thingsFlow,
settingALiveData.asFlow(),
settingBLiveData.asFlow()
) { data, isSettingA, settingB -> produceUiList(data, isSettingA, settingB) }
// where produceUiList is now a suspend function that wraps
// blocking code using withContext
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
846 次 |
最近记录: |