我有一个使用三个LiveData源的MediatorLiveData。当它们中的任何一个发出新值时,并且我至少有一个值,我就使用这三个值为UI生成输出。
其中两个源是如何排序和过滤列表的用户设置,第三个是从Room数据库流中提取的列表数据。
它看起来像这样:
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
}
}
}
}我正在寻找一种干净的方式来转换成一个SharedFlow,最好没有任何@ExperimentalCoroutinesApi。我遇到的唯一一个SharedFlow构建器函数是callbackFlow,它不适用。你打算在大多数情况下使用flow { ... }.asSharedFlow(...)吗?如果是,在这里会是什么样子?
我还计划将LiveData的两个设置迁移到flows。
发布于 2021-06-09 00:14:47
源流可以使用combine()进行组合,这将创建一个冷流,当收集到该流时,将开始从其源流收集,源流可以是热的也可以是冷的。
我最初在想,我一定是遗漏了什么,应该有一些方法可以直接将热流组合成组合热流。但我意识到,操作符应该只返回冷流,并让您在需要时将其转换回热流,这是有意义的。
在许多情况下,比如我的,让它保持冷淡是完全没有问题的。我只从我的UI中的一个地方收集这个流,所以它只是在收集时才开始组合源,这并不重要。源热流并不关心当前是否有什么东西正在收集它们,或者not...they只是继续发出。
如果我从多个地方或多次收集这个流,那么在组合的流上使用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 withContexthttps://stackoverflow.com/questions/65401721
复制相似问题