Rxjava2.x 封装总结

封装作为java的三大特性之一,相信每个开发者对封装技术点都能说出一些,但是真正到项目实际开发,很多开发者都没有注意,今天这篇博客主要总结一下rxjava2.0使用过程中一些封装。

一、线程调度封装

先上一段简单的代码,比较常见。

Flowable.timer(3000, TimeUnit.MILLISECONDS)
                  .subscribeOn(Schedulers.io())
                  .observeOn(AndroidSchedulers.mainThread())
                  .subscribe(new Consumer() {
                    @Override
                    public void accept(Long aLong) throws Exception {

                    }
                });

上面这段代码只是简单做了一下延迟,很常见的写法,这个应该怎么样优化呢?大家有没有注意线程调度这里,每个接口几乎有线程调度相关的操作,这里可不可以封装一下呢??答案是可以的

/**
     * 统一线程处理
     * @param 
     * @return
     */
    public static  FlowableTransformer rxSchedulerHelper() {    //compose简化线程
        return new FlowableTransformer() {
            @Override
            public Flowable apply(Flowable observable) {
                return observable.subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }

通过使用使用compose()操作符,compose()里接收一个FlowableTransformer对象,FlowableTransformer是个接口,通过实现这个接口,将FlowableTransformer转化成 Publisher,接下来上面倒计时那段代码就可以写成这个样子

Flowable.timer(3000, TimeUnit.MILLISECONDS)
//                  .subscribeOn(Schedulers.io())
//                  .observeOn(AndroidSchedulers.mainThread())
                    .compose(RxUtil.rxSchedulerHelper())
                    .subscribe(new Consumer() {
                    @Override
                    public void accept(Long aLong) throws Exception {

                    }
                });

二、UI、异常相关封装

我们平时网络请求的的代码中,大概的套路都是这样,发请网络请求后,在页面上弹个正在加载的页面,请求成功或者失败后取消正在加载的页面,展示相应的页面。比较笨的方法,每次请求在onStart()中展示进度,onNext()onComplete或取消,展示页面,其实也没毛病,就是代码重复率太高,效率低,接下来我们把这个操作简单的封装一下。

public abstract class CommonSubscriber extends ResourceSubscriber {
    private BaseView mView;
    private String mErrorMsg;
    private boolean isShowErrorState = true;

    protected CommonSubscriber(BaseView view){
        this.mView = view;
    }

    @Override
    public void onError(Throwable e) {
        if (mView == null) {
            return;
        }
        if (mErrorMsg != null && !TextUtils.isEmpty(mErrorMsg)) {
            mView.showErrorMsg(mErrorMsg);
        } else if (e instanceof ApiException) {
            mView.showErrorMsg(e.toString());
        } else if (e instanceof HttpException) {
            mView.showErrorMsg("数据加载失败");
        } else {
            mView.showErrorMsg("未知错误");
        }
        if (isShowErrorState) {
            mView.stateError();
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
         mView.stateLoading();
    }

    @Override
    public void onComplete() {
        mView.stateMain();
    }
}

这里我简单的解释一下,BaseView用于处理View相关的状态的接口,具体写法看自己的业务需求,不多解释。重点看一下ResourceSubscriber这个类,查看源码我们发现此类实现了FlowableSubscriber, Disposable,主要功能是 允许异步取消其订阅相关资源,节省内存而且是线程安全。这样我们就可以在subscribeWith(这个方法可以返回当前订阅的观察者)中使用自定义这个类了。

 Flowable.timer(3000, TimeUnit.MILLISECONDS)
                .compose(RxUtil.rxSchedulerHelper())
                .subscribeWith(new CommonSubscriber(this) {
                    @Override
                    public void onNext(Long aLong) {
                        Log.e(TAG, "accept: 三秒后执行");
                    }
                });

我在CommonSubscriber类中,onStart和onComplete方法中分别打了一个log,输出如下;
这里写图片描述
有图有真相,跟我们预想中的一样,所以我在开发中只需关注onNext()中数据相关的就可以了。

三、服务器返回数据统一封装

我们在平时开发中,后台返回的数据格式都应该一致的(除非你们公司后台是刚毕业的实习生),比较常见的接口返回类型如下,目前我们公司后台数据格式就是这个,当然别的类型也没毛病,大同小异。

    private int code;
    private String message;
    private T data;

通过code判断是否是成功与否,错误信息封装在message中,data就是我们最终关心的数据,正常情况我们一般这么做,我简单写个伪代码:

 if(data.getCode() == 200) {
       return code;
     } else {
        return message;
     }

以上这段代码几乎每个网络请求都要这么写,甚至还要判断data不为空,蜜汁缩进,我们View中最关心的是展示给用户的数据(data)及当发生错误时候展示给用户的提示(message),view(mvp模式中 presenter)并不需要知道怎么来的,接下来我就针对这个情况封装一下。

 /**
     * 统一返回结果处理
     * @param 
     * @return
     */
    public static  FlowableTransformer, T> handleMyResult() {   //compose判断结果
        return new FlowableTransformer, T>() {
            @Override
            public Flowable apply(Flowable> httpResponseFlowable) {
                return httpResponseFlowable.flatMap(new Function, Flowable>() {
                    @Override
                    public Flowable apply(MyHttpResponse tMyHttpResponse) {
                        if(tMyHttpResponse.getCode() == 200) {
                            return createData(tMyHttpResponse.getData());
                        } else {
                            return Flowable.error(new ApiException(tMyHttpResponse.getMessage(), tMyHttpResponse.getCode()));
                        }
                    }
                });
            }
        };
    }

createData()

/**
     * 生成Flowable
     * @param 
     * @return
     */
    public static  Flowable createData(final T t) {
        return Flowable.create(new FlowableOnSubscribe() {
            @Override
            public void subscribe(FlowableEmitter emitter) throws Exception {
                try {
                    emitter.onNext(t);
                    emitter.onComplete();
                } catch (Exception e) {
                    emitter.onError(e);
                }
            }
        }, BackpressureStrategy.BUFFER);
    }

接下来,在我们代码中就可以这样搞了,上面的例子不适用这个了,我截取了一段我们项目中判断当前版本号的代码,如下

 apiService.appversion(test1, test2)            
                .compose(RxUtil>rxSchedulerHelper())
                .compose(RxUtil.handleMyResult())
                .//省略

以上就是我对Rxjava的简单封装,并且已经在项目中实际使用过,使用起来比较舒服,省去很多啰嗦的代码。各位读者发现有什么错误或者有更好的建议,请在下面评论指出,谢谢!

你可能感兴趣的:(Android)