android – 根据需要组合嵌套Observable的最新值

我有一些自定义字段,每个字段都有一个可以使用BehaviorSubject< Value>检索的值.显示的字段基于我从API获得的内容,因此最后我有大量的BehaviorSubject< Value> s.我想将这些值组合成一个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>>,但我不知道该怎么做.

最佳答案 groupBy在这里似乎对我没有帮助.

累积值通常使用扫描完成,在这里您可以使用如下转换:

values.scanWith({ arrayOfNulls<Value>(N) }) { acc, (index, value) ->
    acc.copyOf().apply {
        set(index, value)
    }
}
    .map { it.filterNotNull() }

你可能没有copyOf()就可以逃脱,但我认为在过去累积函数不纯的时候遇到了问题.

顺便说一下,您可以将位置写入值而不是Pair(位置,值).

此外,您可以使用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")
    }
点赞