基于RxJava Retrofit的网络框架(二)

Observable网络框架的解耦和复用

Observer一端的解耦

我们可以看到BaseObserver实际做了errorcode响应,loading控制,对外接口的定义等工作。这几部分工作集中在一个类中有一定的耦合。我们设计的目标是业务使用自定义的Observer或者直接使用BaseObserver都很方便,但目前的设计业务要么使用BaseObserver全部功能,要么自己从头定义,扩展性不强。
我们可以如下优化:

将callback接口化

BaseObserver定义的onSuccess(T)和onFail(boolean isException ,Object object)两个抽象方法是完全面向业务使用者的。可将其抽象为接口:

public interface ObserverCallback <T extends MapiHttpResponse<? extends Serializable>>{

    /**
     * 请求成功
     * @param t
     */
    void onSuccess(T t);

    /**
     * 请求失败
     * @param isException true:返回Throwable false:返回String(ErrorMsg)
     * @param object
     */
    void onFail(boolean isException ,Object object);

}

化为接口有两个作用

  1. 规范自定义的Observer的回调接口。
  2. 可以与其他的网络请求调用方式(callback方式,非observable方式),回调接口上统一,降低切换成本。
将loading逻辑和error响应逻辑分离

定义LoadingObserver,其实现ObserverCallback接口

public abstract class LoadingObserver<T extends MapiHttpResponse<? extends Serializable>>
        implements Observer<T> ,ObserverCallback<T>{

    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<T extends MapiHttpResponse<? extends Serializable>>
        extends LoadingObserver<T>{


    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一端做了哪些事情:

  1. 对Request 参数做发送前处理:组合和加密处理
  2. 返回Response 解密处理,Java实体化
  3. 返回Response code码判断及分类

Observable端解耦的目的

  1. 耦合性降低后,方便后续的扩展和组合
  2. 将公共的,不易变化的逻辑下沉

这是最终Observable生成的代码:

private static Observable<R> sendRequest(final HttpRequest request,final TypeReference<R> 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 Observable<R> sendRequest(final HttpRequest request,final TypeReference<R> t)
  {
        return NetHelper.getApiObservable(request)
              .map(new JavaBeanFunc(t))
              .compose(ResponseTransformer.handleResult())
              .subscribeOn(Schedulers.io())
              .observeOn(AndroidSchedulers.mainThread());
}

以上可以看出Observable的生成过程中,除了一部分的逻辑放入的Request的接口中用于扩展,其他的功能在Observable的生成过程中以链式调用的方式存在,每个链式调用的功能由一个类承担。这也是rxjava的优势所在,在调用方式上天然地将各部分解耦了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,585评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,398评论 25 707
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,680评论 2 59
  • 欢迎访问我的博客 JavaScript是单线程执行的,代码是一句一句执行的,而异步任务,如定时器或者动画,会被压入...
    惊鸿三世阅读 815评论 0 3
  • 表面上不是那个自己 内心里还是不能把你忘记 生于现实时不敢不忧患 只想把最好的自己呈现给你 有时无奈的祈祷你比我过...
    蛰伏的爱lby阅读 175评论 0 0