Retrofit + RxJava 业务状态重定向及分离

问题

本文主要介绍了在 Retrofit + RxJava 环境下更优雅的解决了以下两个问题:

  1. 将接口业务上的失败重定向到 onError(Throwable e) 输出;
  2. 业务成功时分离出 data 数据由 onNext(T t) 输出;

场景

一般来说,一个友好的接口返回 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-业务状态重定向及分离/

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值