RxJava&Retrofit错误预处理
Posted this.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RxJava&Retrofit错误预处理相关的知识,希望对你有一定的参考价值。
RxJava和retrofit配合使用进行网络请求在实际开发中还是很强大的。在实际开发中,再对网络请求返回的结果往往要先进行预处理。即先过滤了错误的信息,在执行onNext()方法时只需要考虑正确的结果下如何处理就行。
以一个正常的Json返回为例:
"status": 1,
"errmsg": "OK",
"data": ...
"status": 0,
"errmsg": "error",
"data":
status表示请求结果正确(1)还是错误(0),errmsg为错误信息,data为正请求正确返回的数据。
此时,在Java代码中就可以创建一个JavaBean对象来对应该Json格式:
public class BaseResponse<T>
public int status;
public String errmsg;
public T data;
public boolean isStatusOK()
return status == 1;
由于在onNext()中只需要正确结果中的data,所以需要进行错误信息的过滤:
/**
* 结果预处理,此方法用于规范的JSON格式
* Observable<BaseResponse<T>> -> Observable<T>
* @param <T>
* @return
*/
public static <T> Observable.Transformer<BaseResponse<T>, T> handleResult()
return new Observable.Transformer<BaseResponse<T>, T>()
@Override
public Observable<T> call(Observable<BaseResponse<T>> rObservable)
return rObservable.flatMap(new Func1<BaseResponse<T>, Observable<T>>()
@Override
public Observable<T> call(BaseResponse<T> tBaseResponse)
if (tBaseResponse.isStatusOK())
return createData(tBaseResponse.data);
else
//如果发生错误就会在onError()方法处进行处理
return Observable.error(new ServerException(tBaseResponse.errmsg));
);
;
private static <T> Observable<T> createData(final T data)
return Observable.create(new Observable.OnSubscribe<T>()
@Override
public void call(Subscriber<? super T> subscriber)
try
subscriber.onNext(data);
subscriber.onCompleted();
catch (Exception e)
subscriber.onError(e);
);
然后在网络请求时便可传入上述变换器来进行转换,以登录为例:
//定义请求借口
public interface ApiService
@FormUrlEncoded
@POST("login")
Observable<BaseResponse<MyData>> login(@Field("userPhone") String userPhone
,@Field("userPass") String psw, @Field("SeriesID") int SeriesID);
//此方法位于Model层,对于onNext的处理在presenter层
@Override
public Observable<MyData> login(String phone, String psw)
return Api.getDefault()
.login(phone, psw, AppConfig.SERIAL_ID)
.compose(RxTransformer.<BaseResponse<MyData>>schedules_io_main()) //线程调度
.compose(RxTransformer.<MyData>handleResult()); //转换为正确的结果
//presenter层
@Override
public void login(String phone, String psw)
mManager.add(mModel.login(phone, psw).subscribe(new RxSubscriber<MyData>(mContext)
@Override
public void _onNext(MyData myData)
//处理myData
));
以上就可以实现规范的Json数据处理。
但是,有时候服务器端返回的Json并非都是完全规范的,比如,最近遇到的一种格式:
"status": 1,
"errmsg": "OK",
"data": ...
"status": 0,
"errmsg":
"code": 101,
"content": "error!"
,
"data":
其中errmsg是不确定的类型,可以为String,也可以为JavaBean,由status决定,导致无法像data一样用泛型直接处理。
这时候就需要自己手动去根据status的值来解析数据,BaseResponse也有所修改:
//不能直接解析errmsg,如果类型不正确会报错
public class BaseResponse<T>
public int status;
public T data;
public boolean isStatusOK()
return status == 1;
此时,定义请求接口时返回需要修改:
public interface ApiService
@FormUrlEncoded
@POST("login")
//返回String,用来手动解析
Observable<String> login(@Field("userPhone") String userPhone
,@Field("userPass") String psw, @Field("SeriesID") int SeriesID);
这里,由于返回的是String类型,所以要为retrofit添加转换器:
compile ‘com.squareup.retrofit2:converter-scalars:2.0.0-beta4’
其他转换器也可在https://github.com/square/retrofit 中查找
retrofit = new Retrofit.Builder()
.client(okHttpClient)
.addConverterFactory(ScalarsConverterFactory.create()) //添加字符串转换
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.baseUrl(BASE_URL)
.build();
变换器就应该有所修改:
/**
* 结果预处理,此方法用于处理不规范的JSON格式,代码需根据不规范的形式进行修改
* Observable
* @param cls 直接解析的JavaBean类型
* @param <T>
* @return
*/
public static <T> Observable.Transformer<String, T> handleResultFromString(final Class<T> cls)
if (cls == null)
throw new NullPointerException("cls cannot be null!");
return new Observable.Transformer<String, T>()
@Override
public Observable<T> call(Observable<String> sObservable)
return sObservable.flatMap(new Func1<String, Observable<T>>()
@Override
public Observable<T> call(String s)
Gson gson = new Gson();
Type type = new TypeToken<BaseResponse<T>>().getType();
//解析Json对应到BaseResponse
BaseResponse<T> response = gson.fromJson(s, type);
if (response.isStatusOK()) //结果正确
if (response.data == null)
try
return createData(cls.newInstance());
catch (InstantiationException e)
e.printStackTrace();
catch (IllegalAccessException e)
e.printStackTrace();
return createData(null);
else //data不为空,解析到传入的泛型T中
T t = gson.fromJson(response.data.toString(), cls);
return createData(t);
else
//如果发生错误则解析到BaseError中,最终由onError处理
BaseError error = gson.fromJson(s, BaseError.class);
return Observable.error(new ServerException(error.errmsg.content));
);
;
public class BaseError
public ErrMsg errmsg;
public class ErrMsg
public int code;
public String content;
此时,在model层应用转换器:
@Override
public Observable<MyData> login(String phone, String psw)
return Api.getDefault()
.login(phone, psw, AppConfig.SERIAL_ID)
.compose(RxTransformer.<String>schedules_io_main())
.compose(RxTransformer.handleResultFromString(MyData.class));
通过上述的实现则完成了错误的预处理,当然,不规范的情况可能不止这一种,其他类型的也需要手动去进行解析。
以上是关于RxJava&Retrofit错误预处理的主要内容,如果未能解决你的问题,请参考以下文章
Android Retrofit+RxJava 优雅的处理服务器返回异常错误
使用 Zip 运算符、Rxjava 和 Retrofit 处理错误
Rxjava +Retrofit 你需要掌握的几个技巧,Retrofit缓存,RxJava封装,统一对有无网络处理,异常处理, 返回结果问题
RxJava/Retrofit - 如何强制用户使用特定的订阅者子类?
预期 BEGIN_OBJECT 但在路径 $ 处是 BEGIN_ARRAY - 使用 RxJava 处理 JSONArray 响应的 Retrofit2