You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Observable终止后doCancel调用次数是否与doOnSubscribe次数相等?

结论

你当前的写法无法保证变量c最终取值为0。

原因分析

你用到的两个回调触发场景不匹配:

  • doOnSubscribe 会在订阅成功建立时固定触发,所以每次成功订阅c都会执行+1,这个逻辑符合预期。
  • doOnCancel 仅在订阅被主动取消时才会触发,如果Observable正常执行完成发送onComplete、或者执行过程中抛出异常发送onError终止,这两种最常见的正常终止场景都不会触发doOnCancel,对应的c--不会执行,最终c就会出现大于0的情况。

修正方案

如果要覆盖所有终止场景(主动取消、正常结束、异常结束),保证每次订阅对应的加减操作成对执行,把doOnCancel替换为doFinally即可,doFinally会在Observable所有终止场景下统一触发:

var c = 0
fun getItemsFromDb(): Observable<Data>

getItemsFromDb()
  .doOnSubscribe { c++ }
  .doFinally { c-- }

如果是RxJava 2.x以下版本不支持doFinally,也可以同时添加两个回调实现相同效果:

getItemsFromDb()
  .doOnSubscribe { c++ }
  .doAfterTerminate { c-- } // 覆盖onComplete、onError场景
  .doOnCancel { c-- } // 覆盖主动取消场景

额外注意

如果这段代码运行在多线程环境下,普通的var c = 0会有并发读写风险,建议替换为AtomicInteger保证加减操作的原子性。


内容的提问来源于stack exchange,提问作者ivan8m8

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 06:48:01