本文主要介绍了在 Retrofit + RxJava 环境下更优雅的解决了以下两个问题:
一般来说,一个友好的接口返回 json 应该是这样的:
{
"code":200,
"codeMsg":"查询成功!",
"data":{ "city":"北京", "temperature":"8℃~20℃", "weather":"晴转霾" } }
或者这样的:
{
"code":200,
"codeMsg":"查询成功!",
"data":[ { "city":"北京", "temperature":"8℃~20℃", "weather":"晴转霾" }, { "city":"南京", "temperature":"12℃~21℃", "weather":"晴" } ] }
如果约定好,code == 200,表示业务成功。其他表示业务失败,codeMsg 更详细地描述业务状态信息。例如:
{
"code":"400",
"codeMsg":"未知的城市" }
要知道,利用 Retrofit + Gson (或者其他 Converter ) 可以将返回的 Json 的转换为对象的,那么可以定义以下返回通用类 Model :
/** * CommonResponse - 通用类 * 泛型 T 可以为 List<object> , 也可以是 Object , 也可以为空。 */
public class CommonResponse<T> {
private int code;
private String codeMsg;
private T data;
public int getCode() {
return code;
}
public String getCodeMsg() {
return codeMsg;
}
public T getData() {
return data;
}
/** * 根据 code 码判断业务状态 * code == 2xx,表示业务成功。其他表示业务失败,codeMsg 进一步描述业务状态。 */
public boolean isSuccess() {
return code / 100 == 2;
}
}
为了解决上面提出的两个问题,这里可以使用 RxJava 中的 lift() 来自定义操作:
/** * 这里为了示例,简化了Retrofit Service、Api 创建的过程。 */
JKApi mApi = JKService.createJKService();
mApi.getWeatherForCity("北京").lift(new Observable.Operator<T, CommonResponse<T>>() {
@Override
public Subscriber<? super CommonResponse<T>> call(final Subscriber<? super T> subscriber) {
return new Subscriber<CommonResponse<T>>() {
@Override
public void onCompleted() {
subscriber.onCompleted();
}
@Override
public void onError(Throwable e) {
subscriber.onError(e);
}
@Override
public void onNext(CommonResponse<T> tCommonResponse) {
if (tCommonResponse.isSuccess())
subscriber.onNext(tCommonResponse.getData());
else
subscriber.onError(new Throwable(tCommonResponse.getCodeMsg()));
}
};
}
});
上面的 lift() 操作想要对每一个符合这样标准的接口都通用,并且顺便对线程指定进行封装。可以 implements Observable.Transformer
public class RedirectResponseTransformer<T> implements Observable.Transformer<CommonResponse<T>, T> {
@Override
public Observable<T> call(
Observable<CommonResponse<T>> CommonResponseObservable) {
return CommonResponseObservable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.lift(new Observable.Operator<T, CommonResponse<T>>() {
@Override
public Subscriber<?super CommonResponse<T>> call(
final Subscriber<?super T> subscriber) {
return new Subscriber<CommonResponse<T>>() {
@Override
public void onCompleted() {
subscriber.onCompleted();
}
@Override
public void onError(Throwable e) {
subscriber.onError(e);
}
@Override
public void onNext(
CommonResponse<T> tCommonResponse) {
if (tCommonResponse.isSuccess()) {
subscriber.onNext(tCommonResponse.getData());
} else {
subscriber.onError(new Throwable(
tCommonResponse.getCodeMsg()));
}
}
};
}
});
}
}
最后我们使用 Observable.compose(Transformer transformer) 方法将以上的封装加入到 Rx-Chain 中去:
/** * 这里为了示例,简化了Retrofit Service、Api 创建的过程。 */
JKApi mApi = JKService.createJKService();
mApi.getWeatherForCity("北京")
.compose(new RedirectResponseTransformer<WeatherModel>())
.subscribe(new Subscriber<WeatherModel>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
showShortToast(e.toString());
}
@Override
public void onNext(WeatherModel weatherModel) {
// do something like refresh ui
}
});
到这里,针对上文提出的两个问题已经做了封装。其实利用 RxJava 强大的运算符还可以做很多封装。例如:针对特定异常显示Toast、onComplete() 回调中 dismiss loadingDialog 等。
来自:http://jkyeo.com/2016/03/01/Retrofit-RxJava-业务状态重定向及分离/