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

标签: RetrofitRxJava
2135人阅读 评论(0) 收藏 举报
分类:

问题

本文主要介绍了在 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
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:10388563次
    • 积分:74525
    • 等级:
    • 排名:第24名
    • 原创:505篇
    • 转载:916篇
    • 译文:4篇
    • 评论:2228条
    打赏
    如果您认为本博客不错,读后觉得有收获,不妨打赏赞助我一下,让我有动力继续写出高质量的博客。



    赠人玫瑰,手有余香。分享技术,传递快乐。

    有心课堂,传递的不仅仅是技术!

    QQ交流群:183899857

    有心课堂会员,请加入VIP QQ交流群:213725333

    github
    我的视频
    博客专栏
    最新评论