Android RxJava3中Repository层SingleSubject订阅线程切换问题排查
问题原因解释
你遇到的线程切换是SingleSubject的标准行为,核心原因如下:
SingleSubject属于热流类型,本身不自带任何线程调度逻辑,事件回调的执行线程完全由两个条件决定:订阅时SingleSubject是否已经发射过结果、订阅动作发生的线程- 你在
fetchData中订阅时,网络请求还未返回,SingleSubject处于未完成状态,此时注册的观察者会等待网络请求的结果回调:你配置的Retrofit默认把请求放到IO线程执行,因此网络请求返回后会在IO线程调用SingleSubject的onSuccess方法,所有已注册的观察者回调都会在这个IO线程执行,对应你日志中线程ID为224的输出。 - 后续ViewModel在主线程调用
getfilteredDerivedSubject2订阅时,网络请求已经执行完成,SingleSubject已经缓存了成功/失败结果:RxJava中已经终止的SingleSubject对新订阅者会直接在当前订阅发生的线程同步发射缓存的结果,不需要等待上游事件,因此你的回调直接运行在调用订阅时的主线程,对应日志中线程ID为2的输出。
- 你在
修复方案
如果需要统一所有订阅者的回调线程,不管订阅时机是早是晚,只需要在对外暴露Subject时统一加上observeOn指定目标调度器即可,示例如下:
public Single<List<DerivedObject2>> getfilteredDerivedSubject2(){ // 若需要指定其他线程,替换为对应Scheduler即可,比如Schedulers.io() return filteredDerivedSubject2.observeOn(AndroidSchedulers.mainThread()); }
注意这种场景下subscribeOn不会生效,只有observeOn可以控制下游回调的执行线程。
内容的提问来源于stack exchange,提问作者programmingmanwithaplan
相关产品推荐
相关产品推荐

