如何转换 3 个或更多 LiveData。在 Android 中合并为一个 Flow
How to convert 3 or more LiveData. into a single Flow in Android
视图模型有来自 3 个不同 api 调用的 3 个实时数据。现在,我想在回收站视图的列表中将所有数据一起显示为不同的卡片。
最好的方法是什么?
目前我正在使用 MediatorLiveData,但现在我需要进行 4 次不同的 api 调用,这将生成 4 个实时数据对象。因此,我正在尝试使用 kotlin flow 来解决这个问题。我怎样才能结合起来。来自不同用例的 4 个不同的实时数据进入单个流对象,然后将其收集在片段中?
以下是方法,我尝试使用组合方法组合 3 个实时数据:
private val flow1 = pojo1UseCase.data.asFlow()
private val flow2 = pojo2UseCase.data.asFlow()
private val flow3 = pojo3UseCase.data.asFlow()
suspend fun combine() {
flow1.combine(flow2) { f1, f2 ->
listOf(f1.right(), f2.right())
}.combine(flow3) { f1, f3 ->
listOf(f1, f3.right())
}.collect { list ->
list.forEach {
ba = it as? Pojo1
oc = it as? Pojo2
sd = it as? Pojo3
}
}
}
我在这里调用 collect 只是为了测试目的,但我打算在片段中调用 collect 方法。
有人可以分享做类似事情的更好方法吗?
假设这很简单,并且您只希望每个 LiveData 有一个值,combine
应该没问题,但您可以使用带有三个参数的变体。
此外,由于它只是另一个冷流,因此可以简单地属性。冷流将由 LiveDatas 支持,因此如果在收到结果并收集流后出现某些情况,检索到的值不会丢失。只有在收集时才需要挂起功能。
val combined: Flow<List<Any>> =
combine(flow1, flow2, flow3) { a, b, c -> listOf(a, b, c) }
但我会推荐一个 class 来固定你的物体,这样你就不必在它们出来时施放它们。
data class MyResult(pojo1: Pojo1, pojo2: Pojo2, pojo3: Pojo3)
val combined: Flow<MyResult> = combine(flow1, flow2, flow3, ::MyResult)
因为没有什么可以自动取消这些流,如果你做一个收集它们的暂停功能,我认为你需要使用 first()
否则它会无限期暂停。
suspend fun combine() = with(combined.first()) {
ba = pojo1
oc = pojo2
sd = pojo3
}
或者您可以使用 take(1)
定义您的流程,使其在第一个结果出现时自动完成。
val combined: Flow<MyResult> = combine(flow1, flow2, flow3, ::MyResult).take(1)
根据评论编辑:
如果你想无限期地收集它们,你可以在内部开始,或者你可以创建一个函数,你将调用一次来开始收集。你不应该使用挂起函数,因为无论哪个协程调用它都会永远卡在 collect()
调用上。它应该只是一个常规函数,它启动自己的协程来收集它。
init {
combined.onEach {
with(it) {
ba = pojo1
oc = pojo2
sd = pojo3
}
}.launchIn(viewModelScope)
}
// or:
fun startCombining() {
combined.onEach {
with(it) {
ba = pojo1
oc = pojo2
sd = pojo3
}
}.launchIn(viewModelScope)
}
视图模型有来自 3 个不同 api 调用的 3 个实时数据。现在,我想在回收站视图的列表中将所有数据一起显示为不同的卡片。
最好的方法是什么?
目前我正在使用 MediatorLiveData,但现在我需要进行 4 次不同的 api 调用,这将生成 4 个实时数据对象。因此,我正在尝试使用 kotlin flow 来解决这个问题。我怎样才能结合起来。来自不同用例的 4 个不同的实时数据进入单个流对象,然后将其收集在片段中?
以下是方法,我尝试使用组合方法组合 3 个实时数据:
private val flow1 = pojo1UseCase.data.asFlow()
private val flow2 = pojo2UseCase.data.asFlow()
private val flow3 = pojo3UseCase.data.asFlow()
suspend fun combine() {
flow1.combine(flow2) { f1, f2 ->
listOf(f1.right(), f2.right())
}.combine(flow3) { f1, f3 ->
listOf(f1, f3.right())
}.collect { list ->
list.forEach {
ba = it as? Pojo1
oc = it as? Pojo2
sd = it as? Pojo3
}
}
}
我在这里调用 collect 只是为了测试目的,但我打算在片段中调用 collect 方法。 有人可以分享做类似事情的更好方法吗?
假设这很简单,并且您只希望每个 LiveData 有一个值,combine
应该没问题,但您可以使用带有三个参数的变体。
此外,由于它只是另一个冷流,因此可以简单地属性。冷流将由 LiveDatas 支持,因此如果在收到结果并收集流后出现某些情况,检索到的值不会丢失。只有在收集时才需要挂起功能。
val combined: Flow<List<Any>> =
combine(flow1, flow2, flow3) { a, b, c -> listOf(a, b, c) }
但我会推荐一个 class 来固定你的物体,这样你就不必在它们出来时施放它们。
data class MyResult(pojo1: Pojo1, pojo2: Pojo2, pojo3: Pojo3)
val combined: Flow<MyResult> = combine(flow1, flow2, flow3, ::MyResult)
因为没有什么可以自动取消这些流,如果你做一个收集它们的暂停功能,我认为你需要使用 first()
否则它会无限期暂停。
suspend fun combine() = with(combined.first()) {
ba = pojo1
oc = pojo2
sd = pojo3
}
或者您可以使用 take(1)
定义您的流程,使其在第一个结果出现时自动完成。
val combined: Flow<MyResult> = combine(flow1, flow2, flow3, ::MyResult).take(1)
根据评论编辑:
如果你想无限期地收集它们,你可以在内部开始,或者你可以创建一个函数,你将调用一次来开始收集。你不应该使用挂起函数,因为无论哪个协程调用它都会永远卡在 collect()
调用上。它应该只是一个常规函数,它启动自己的协程来收集它。
init {
combined.onEach {
with(it) {
ba = pojo1
oc = pojo2
sd = pojo3
}
}.launchIn(viewModelScope)
}
// or:
fun startCombining() {
combined.onEach {
with(it) {
ba = pojo1
oc = pojo2
sd = pojo3
}
}.launchIn(viewModelScope)
}