RxJava练武场是一个rxjava在项目中应用的小系列,包括:
Observable网络框架的解耦和复用
Observer一端的解耦
我们可以看到BaseObserver实际做了errorcode响应,loading控制,对外接口的定义等工作。这几部分工作集中在一个类中有一定的耦合。我们设计的目标是业务使用自定义的Observer或者直接使用BaseObserver都很方便,但目前的设计业务要么使用BaseObserver全部功能,要么自己从头定义,扩展性不强。 我们可以如下优化:
将callback接口化
BaseObserver定义的onSuccess(T)和onFail(boolean isException ,Object object)两个抽象方法是完全面向业务使用者的。可将其抽象为接口:
public interface ObserverCallback>{ /** * 请求成功 * @param t */ void onSuccess(T t); /** * 请求失败 * @param isException true:返回Throwable false:返回String(ErrorMsg) * @param object */ void onFail(boolean isException ,Object object);}复制代码
化为接口有两个作用
- 规范自定义的Observer的回调接口。
- 可以与其他的网络请求调用方式(callback方式,非observable方式),回调接口上统一,降低切换成本。
将loading逻辑和error响应逻辑分离
定义LoadingObserver,其实现ObserverCallback接口
public abstract class LoadingObserver> implements Observer ,ObserverCallback { protected BaseContext mBaseContext; public LoadingObserver(BaseContext baseContext){ mBaseContext = baseContext; } @Override public void onSubscribe(Disposable d) { if (isShowProgress()) { showProgress(true); } } @Override public void onNext(T t) { if (isShowProgress()) { showProgress(false); } onSuccess(t); } @Override public void onError(Throwable e) { if (isShowProgress()) { showProgress(false); } } @Override public void onComplete() { if (isShowProgress()) { showProgress(false); } } protected void showProgress(boolean isShow){ if (mBaseContext != null) { mBaseContext.showLoading(isShow); } } /** * 网络请求是否loading显示 * @return */ protected boolean isShowProgress(){ return true; }}复制代码
这样做: 1、将更为通用的loading逻辑抽离,使其可以被独立使用或继承。 2、如果app存在不同业务线,可将error影响单独处理(不同业务线code定义可能不同),将loadingObserver类下沉,适配多业务线情况
BaseObserver代码如下:
public abstract class MapiObserver> extends LoadingObserver { public MapiObserver(BaseContext baseContext){ super(baseContext); } @Override public void onError(Throwable e) { super.onError(e); handleError(e); } private void handleError(Throwable e){ //handle error code }}复制代码
至此,Observer被分为了三层,原来BaseObserver这一层可以由多个更为具体的Observer来扩展。每一层都有自己的扩展功能。
ObservableSource一端的解耦
我们看下Observable一端做了哪些事情:
- 对Request 参数做发送前处理:组合和加密处理
- 返回Response 解密处理,Java实体化
- 返回Response code码判断及分类
Observable端解耦的目的
- 耦合性降低后,方便后续的扩展和组合
- 将公共的,不易变化的逻辑下沉
这是最终Observable生成的代码:
private static ObservablesendRequest(final HttpRequest request,final TypeReference t) { return NetHelper.getApiObservable(request) .map(new JavaBeanFunc(t)) .compose(ResponseTransformer.handleResult()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread());}复制代码
Request请求params参数组合加密处理放到何处?
前面一章已经提到,params是通过HttpRequest类中的getURLParam()方法完成。 原因有2点 1、params定义在HttpRequest中,在Httprequest类中拿最方便。 2、组合和加密的过程如果需要定制,那么直接在HttpRequest子类中就可以,和框架不会有耦合。
Response解密处理,Java实体化,在何处处理?
Response解密处理网上有两种处理方式, 1、在okhttp里使用interceptor拦截器解密 2、ResponseTransformer中处理。 这两种方式都有问题: 虽然app内部一般解密方式不变,但是要适应多业务线,或者作为适应性更广的框架来讲,这块解密逻辑放到框架中显然耦合性太高。 我们采用的方式是定义接口:
public interface ResponseDecryptHandler { String decrypt(String var1) throws IOException;}复制代码
HttpRequest类中定义实现接口,并将这种解密方式作为Convertor设置给Retrofit,这样将加密的逻辑耦合转移到了HttpRequest基类中
addConverterFactory(SecurityConvertFactory.create(request.responseDecryptHandler()))复制代码
对于JavaBean实体化,一般都采用fastJson方式,这里我们通过map操作符完成,作为链式调用中的一环出现,替换方便。
.map(new JavaBeanFunc(t))复制代码
Response的code解析,在何处处理?
前面提到,response的code分为了解析和处理两个部分,分别放在observable和observer中完成。其中ResponseTransformer是用于解析response的返回值。 ErrorResumeFunction和ResponseFunction分别是网络错误和业务错误,网络错误不会变,业务错误的判断是可能扩展的。ResponseFunction的实现是可以多样的。
private static ObservablesendRequest(final HttpRequest request,final TypeReference t) { return NetHelper.getApiObservable(request) .map(new JavaBeanFunc(t)) .compose(ResponseTransformer.handleResult()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread());}复制代码
以上可以看出Observable的生成过程中,除了一部分的逻辑放入的Request的接口中用于扩展,其他的功能在Observable的生成过程中以链式调用的方式存在,每个链式调用的功能由一个类承担。这也是rxjava的优势所在,在调用方式上天然地将各部分解耦了。