我有一些自定义字段,每个自定义字段都有一个可以使用BehaviorSubject<Value>
进行检索的值。显示的字段是基于我从API中获得的信息,因此最后我有n个BehaviorSubject<Value>
。我想将这些值组合到一个Observable<List<Value>>
中,其中列表包含这些字段的最新值(顺序无关紧要)。但是,问题在于这些字段并非全部同时可用,因为它们是在加载UI时创建的,因此我无法在主题列表中使用Observable.combineLatest
。
我目前要做的是创建以下变量:
private val values = BehaviorSubject.create<Pair<Int, Value>>()
我使用该主题来订阅该领域的所有主题,但首先将主题与它们的位置对应起来,并进行配对。
fieldSubject.map {
Pair(position, value)
}.subscribe(values)
然后我要做的是根据值在一对中的位置将它们分组,并得到一个Observable<List<Value>>
,其中列表包含每个位置的最新值。但是,我不知道在使用groupBy
将它们分组之后如何继续:
values.groupBy {
it.first
}
这将产生一个Observable<GroupedObservable<Pair, Value>>>
。最后,这就是我认为应该到达Observable<List<Value>>
的方式,但是我不知道该怎么做。
答案 0 :(得分:1)
groupBy
在这里似乎对我没有帮助。
通常使用scan
完成值的累加,在这里您可以使用如下转换:
values.scanWith({ arrayOfNulls<Value>(N) }) { acc, (index, value) ->
acc.copyOf().apply {
set(index, value)
}
}
.map { it.filterNotNull() }
如果没有copyOf()
,您可能会逃脱,但是我认为过去,当累加器功能不纯净时,我会遇到问题。
顺便说一句,您可以写position to value
而不是Pair(position, value)
。
此外,您可以使用merge
来获取Observable<Pair<Int, Value>>
,而不是创建BehaviorSubject
并将其手动预订到所有字段:
Observable.mergeArray(
fieldX.map { 0 to it },
fieldY.map { 1 to it },
fieldZ.map { 2 to it }
// ...
)
因此,总的来说,您可以拥有一个可以为您完成所有任务的函数:
inline fun <reified T : Any> accumulateLatest(vararg sources: Observable<out T>): Observable<List<T>> {
return Observable.merge(sources.mapIndexed { index, observable ->
observable.map { index to it }
})
.scanWith({ arrayOfNulls<T>(sources.size) }) { acc, (index, value) ->
acc.copyOf().apply {
set(index, value)
}
}
.map { it.filterNotNull() }
}
然后致电:
accumulateLatest(fieldX, fieldY, fieldZ)
.subscribe {
println("Latest list: $it")
}