RxKotlin中条件判断与循环内使用andThen()操作符的执行异常及返回值未使用警告问题
嘿,这个问题其实是RxJava/RxKotlin里一个很容易踩的坑——Rx的操作符都是返回新的流对象,不会修改原对象,而你用apply的方式刚好忽略了这个核心点,导致内部的andThen完全没生效,还触发了IDE的警告。
咱们先拆解第一个例子:
你写的代码里,operation.apply { ... }最后返回的还是原来的operation对象,而你在apply里调用的andThen(thisDoesNotExecute()),虽然创建了一个包含后续操作的新Completable,但这个新对象没有被保留或使用,相当于白调用了。所以最终执行的只有operation.andThen(thisExecutes()),中间的thisDoesNotExecute()根本没被加入到执行链里,自然不会运行。IDE的警告“ The result of andThen is not used”就是在提醒你:你调用了andThen但没利用它的返回值,这是无效操作。
解决这个问题的核心是必须保留并使用andThen返回的新Completable,可以换掉apply,改用run或者直接用条件判断构建链式结构:
operation .run { // 根据条件决定是否追加后续操作 if (true) andThen(thisDoesNotExecute()) else this } .andThen(thisExecutes())
或者更直白的写法:
val baseCompletable = operation val chainedCompletable = if (true) { baseCompletable.andThen(thisDoesNotExecute()) } else { baseCompletable } chainedCompletable.andThen(thisExecutes())
再看第二个循环的例子,问题本质一样:你在apply里循环调用andThen(operation(item)),每次调用都生成了新的Completable,但这些新对象都被丢弃了,最终执行的只有最初的operation(aList[0])。
要实现依次执行所有列表元素的operation,你需要把这些操作串联成一条完整的链,可以用fold来累积这个链式结构:
if (aList.isEmpty()) { Completable.complete() // 空列表直接返回完成 } else { // 从第一个元素的operation开始,逐个追加后续元素的operation aList.drop(1).fold(operation(aList[0])) { acc, item -> acc.andThen(operation(item)) } } .subscribe() // 最后订阅整个链式结构
这样fold会把每个operation(item)依次串联到之前的Completable后面,最终整个链会按顺序执行所有操作。
总结一下:Rx的流对象是不可变的,任何操作符(比如andThen)都不会修改原对象,而是返回一个包含新逻辑的新对象。所以一定要记住:必须使用操作符返回的新对象,才能让你的后续逻辑生效,像apply这种返回原对象的函数,在Rx链式调用里很容易导致这类问题。
备注:内容来源于stack exchange,提问作者RiesenChicken

