如何实现s1仅触发一次、o1多次触发时的Zip操作及关联处理?
RxJava 操作问题解答
让我来一步步帮你解决这两个RxJava的实际问题哈~
问题1:如何对仅触发一次的s1和多次触发的o1执行Zip操作?
首先得搞清楚zip操作符的核心特性:它必须等每个数据源都发射一个元素,才会把这些元素组合起来输出一次。你的s1是Single类型,转成Observable后只会发射一次元素就完结了;而o1是可以多次发射的Observable,这样第一次zip能成功组合,但o1后续发射的元素就找不到s1对应的元素了——因为s1已经结束了,没法再提供新元素。
解决思路很简单:让s1的结果重复发射,这样o1每发一个元素,都能匹配到s1的结果。我们可以用repeat()操作符来实现:
val s1 = Single.fromCallable { Log.d("so","executing s1") "hello" }.cache() // 模拟o1多次触发的场景 val o1 = Observable.create<String> { emitter -> emitter.onNext("first trigger") emitter.onNext("second trigger") emitter.onNext("third trigger") } // 关键:将s1转成Observable并重复发射结果 Observable.zip( s1.toObservable().repeat(), o1, BiFunction<String, String, Array<String>> { sVal, oVal -> arrayOf(sVal, oVal) } ).subscribe { result -> Log.d("so", "组合结果:${result[0]} + ${result[1]}") }
这样运行后,o1的每一次触发都会和s1的"hello"组合输出,完全符合你的需求。
问题2:s1完成后,针对多次触发的o1每次执行对应操作
你想要的是先等s1执行完成,再处理o1的每一次触发,其实完全不需要用zip——zip是用来同步多个数据源的元素发射节奏,而你这里是串行依赖关系:s1完成后才处理o1。
最符合RxJava风格的实现是用flatMapObservable,链式处理逻辑:
val s1 = Single.fromCallable { Log.d("so","executing s1") "hello" }.cache() val o1 = Observable.create<String> { emitter -> emitter.onNext("trigger 1") emitter.onNext("trigger 2") } s1.flatMapObservable { s1Result -> // s1完成后,订阅o1,每次触发时结合s1的结果处理 o1.map { o1Trigger -> "已完成s1(结果:$s1Result),正在处理o1触发:$o1Trigger" } }.subscribe { processedContent -> Log.d("so", processedContent) }
如果觉得链式调用有点绕,也可以用更直观的嵌套订阅(不过链式更推荐,因为能更好地管理生命周期和错误处理):
s1.subscribe { s1Result -> o1.subscribe { o1Trigger -> // 每次o1触发时执行你需要的操作 Log.d("so", "s1完成后处理o1:$o1Trigger,s1结果:$s1Result") } }
这样就能实现:s1先执行完毕,之后o1每触发一次,就执行对应的操作。
内容的提问来源于stack exchange,提问作者Damn Vegetables
相关产品推荐
相关产品推荐

