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

Retrofit2+RxJava2遇NetworkOnMainThreadException及错误捕获求助

问题1:解决NetworkOnMainThreadException异常

你的错误代码缺失了subscribeOn(Schedulers.io())和observeOn(AndroidSchedulers.mainThread())调度器配置。Retrofit结合RxJava时,若不指定subscribeOn,网络请求会默认在当前线程(主线程)执行,触发Android的网络主线程限制。

修正后的代码:

Disposable disposable = apiInterface.getArea("4744", ".")
        .subscribeOn(Schedulers.io()) // 指定网络请求在IO线程执行
        .observeOn(AndroidSchedulers.mainThread()) // 指定结果回调在主线程处理
        .map(response -> Observable.fromIterable(response))
        .flatMap(x -> x)
        .map(Area::getTypeArea)
        .toList()
        .toObservable()
        .subscribe(this::handlerResponse, this::handlerError);

也可以简化RxJava操作符,用flatMapIterable替代嵌套Observable写法:

Disposable disposable = apiInterface.getArea("4744", ".")
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .flatMapIterable(areas -> areas) // 直接将List转为单个Area的流
        .map(Area::getTypeArea)
        .toList()
        .subscribe(this::handlerResponse, this::handlerError);
问题2:捕获HTTP状态错误信息

默认情况下,Retrofit会将HTTP错误(如4xx、5xx)转为HttpException抛出,但直接调用getMessage()会返回null或无意义内容,需要从HttpException中解析状态码和错误响应体。

方式1:修改接口返回类型为Response<T>

将ApiInterface中的方法改为返回Observable<Response<List<Area>>>,主动控制响应处理逻辑:

// ApiInterface 定义
@GET("your-api-path")
Observable<Response<List<Area>>> getArea(@Query("param1") String param1, @Query("param2") String param2);

调用时处理响应:

Disposable disposable = apiInterface.getArea("4744", ".")
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(response -> {
            if (response.isSuccessful()) {
                // 请求成功,处理数据转换
                List<Area> areas = response.body();
                List<String> typeAreas = areas.stream().map(Area::getTypeArea).collect(Collectors.toList());
                handlerResponse(typeAreas);
            } else {
                // 解析HTTP错误信息
                int statusCode = response.code();
                String errorMsg = response.message();
                try {
                    if (response.errorBody() != null) {
                        String errorBody = response.errorBody().string();
                        Log.d("Error", "HTTP错误码: " + statusCode + ", 信息: " + errorMsg + ", 错误体: " + errorBody);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                handlerError(new Throwable("HTTP错误 " + statusCode + ": " + errorMsg));
            }
        }, throwable -> {
            // 处理其他异常(如网络断开、解析失败)
            if (throwable instanceof HttpException) {
                HttpException httpException = (HttpException) throwable;
                Log.d("Error", "HTTP异常码: " + httpException.code() + ", 信息: " + httpException.message());
            }
            handlerError(throwable);
        });

方式2:在原有接口基础上处理HttpException

如果不想修改接口返回类型,可在错误回调中判断异常类型:

private void handlerError(Throwable throwable) {
    if (throwable instanceof HttpException) {
        HttpException httpException = (HttpException) throwable;
        int statusCode = httpException.code();
        String errorMessage = httpException.message();
        
        // 尝试解析错误响应体
        try {
            ResponseBody errorBody = httpException.response().errorBody();
            if (errorBody != null) {
                String errorContent = errorBody.string();
                Log.d("Error", "HTTP状态码: " + statusCode + ", 信息: " + errorMessage + ", 错误内容: " + errorContent);
            } else {
                Log.d("Error", "HTTP状态码: " + statusCode + ", 信息: " + errorMessage);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    } else {
        Log.d("Error ", "响应错误 " + throwable.getMessage());
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 00:35:29