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

RxJava中CompositeDisposable引发两类异常:是否为同一问题?

这俩问题确实是同一根因导致的!

先给你拆解清楚背后的逻辑:

核心问题根源:线程处理失误 + 请求取消时的OkHttp回调失衡

你写的代码里,Observable.create() 直接在内部执行OkHttp网络请求,但没加 subscribeOn(Schedulers.io()) 把网络操作扔去后台线程。这就引发了连锁反应:

  • 如果你的订阅操作(subscribe())是在主线程触发的,那OkHttp的请求就直接在主线程跑了——这本身就违反Android的网络规则。当你调用 CompositeDisposable.clear() 时,如果网络请求还在主线程吭哧跑,自然就会炸出 NetworkOnMainThreadException。
  • 另一方面,CompositeDisposable.clear() 会触发所有Disposable的 dispose(),这会取消正在跑的OkHttp请求。但OkHttp内部有个EventListener机制,需要enter()和exit()成对调用——比如请求刚触发callStart()(调用了enter()),结果中途被取消,对应的callEnd()或callFailed()没机会调用exit(),直接就抛出java.lang.IllegalStateException: Unbalanced enter/exit了。

两步解决所有问题

第一步:把网络操作强制扔去后台线程

给Observable加上subscribeOn(Schedulers.io()),确保OkHttp请求绝不会跑到主线程:

Observable<Stuff> observable = Observable.create(new ObservableOnSubscribe<Stuff>() {
    @Override
    public void subscribe(@NonNull ObservableEmitter<Stuff> e) throws Exception {
        // 执行OkHttp相关操作
        if (!e.isDisposed()) { // 先检查Emitter没被销毁,避免白忙活
            e.onNext(stuff);
            e.onComplete();
        }
    }
})
.subscribeOn(Schedulers.io()) // 这行是关键!把网络操作丢去IO线程
.observeOn(AndroidSchedulers.mainThread()); // 如果要更新UI,再切回主线程

第二步:让Emitter和OkHttp请求的生命周期绑定

在subscribe()方法里,把Emitter的销毁事件和OkHttp请求的取消操作关联起来,同时确保异常和回调都只在Emitter存活时执行:

@Override
public void subscribe(@NonNull ObservableEmitter<Stuff> e) throws Exception {
    OkHttpClient client = new OkHttpClient();
    Request request = new Request.Builder().url("你的接口地址").build();
    Call call = client.newCall(request);
    
    // 绑定:当Emitter被dispose时,自动取消OkHttp请求
    e.setDisposable(Disposables.fromRunnable(() -> {
        call.cancel();
    }));
    
    try {
        Response response = call.execute();
        if (!e.isDisposed()) {
            // 把response解析成Stuff对象
            Stuff stuff = parseResponse(response);
            e.onNext(stuff);
            e.onComplete();
        }
    } catch (IOException ex) {
        if (!e.isDisposed()) {
            e.onError(ex);
        }
    }
}

总结一下

这俩异常其实是同一个问题引发的连锁反应:先是没给网络操作指定后台线程,导致主线程跑网络;然后请求被取消时又没正确清理OkHttp的回调状态。按上面两步改完,就能一次性搞定这两个问题啦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:40:42