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
相关产品推荐
相关产品推荐

