RxJava2 和 Retrofit2 的封装和使用

根据 RxJava2 和 Retrofit2 进行的封装,进行网络请求更加方便。

demo下载地址:https://github.com/sundevin/rxjava2_retrofit2

目前实现:

1, 统一风格的接口
2, 不统一风格的接口
3, 内存泄漏问题
4, 请求过程中 ProgressDialog
5, 自定义证书的 Https 的封装
6, 使用 okHttp 进行下载时进度回调的封装

后面将实现带进度回调的上传功能。

针对 Restful 风格的接口可以直接指定泛型;
内部增加了 StringConverterFactory,非 Restful 风格的接口(如一些第三方接口的数据)可以直接获取到 String,自行进行数据解析;
网络请求过程中可以绑定到当前的 Activity, Activity 关闭的时候会主动停止请求,避免内存泄漏。也可决定是否显示 ProgressDialog;
数据请求前后可以打印 request 和 response 信息,更直观的进行接口调试;
对 https 进行了封装,只需要指定自签名证书即可。
在使用 okHttp 请求的时候,支持进度回调和取消下载。

初始配置

1,项目依赖
    compile 'io.reactivex.rxjava2:rxjava:2.0.7'
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'

    compile 'com.squareup.retrofit2:retrofit:2.2.0'
    compile 'com.squareup.retrofit2:converter-gson:2.2.0'
    compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'

    compile 'com.trello.rxlifecycle2:rxlifecycle:2.0.1'
    // If you want to bind to Android-specific lifecycles
    compile 'com.trello.rxlifecycle2:rxlifecycle-android:2.0.1'
    // If you want pre-written Activities and Fragments you can subclass as providers
    compile 'com.trello.rxlifecycle2:rxlifecycle-components:2.0.1'

运行时可能会有依赖错误,在 androidTestCompile 配置如下即可解决

    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
        exclude group: 'com.google.code.findbugs', module: 'jsr305'
    })
2,OkHttp 配置
        CustomHttpsTrust customHttpsTrust = new CustomHttpsTrust(CertificateManager.trustedCertificatesInputStream());

        okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
                .writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
                .addInterceptor(new HeaderInterceptor()) //添加 header
                .addInterceptor(new LoggingInterceptor())  //请求信息的打印 ,可在 release 时关闭
                .sslSocketFactory(customHttpsTrust.sSLSocketFactory, customHttpsTrust.x509TrustManager)// https 配置
                .build();
3,Retrofit 配置
       static {
        retrofit = new Retrofit.Builder()
                .baseUrl(ApiService.BASE_URL)//配置 baseUrl
                .client(OkHttpHelper.getClient())
                .addConverterFactory(StringConverterFactory.create()) //String 转换
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .validateEagerly(true)
                .build();
    }

Restful 接口

以 demo 中后台返回的标准数据为例,
resultobj 时:

{
      "state":1,
      "msg":"success",
      "result":{}
  }

result 为数组时:

{
      "state":1,
      "msg":"success",
      "result":[]
  }

其中 state 为1时表示业务处理成功,数据正确。反之业务处理有误,用msg 进行提示。
则建立 Entity 如下:

public class HttpResponseResult<T> {

    private static final int SUCCESS_STATUS = 1;
    private String msg;
    private Integer state;
    private T result;

    public boolean isSuccess() {
        return state != null && state == SUCCESS_STATUS;
    }

    public String getMsg() {
        return msg;
    }

    public Integer getState() {
        return state;
    }

    public T getResult() {
        return result;
    }

    @Override
    public String toString() {
        return "HttpResponse{" +
                "msg='" + msg + '\'' +
                ", state=" + state +
                ", result=" + result +
                '}';
    }
}

Object的请求:

    /**
     *  post test
     * @param map
     * @return
     */
    @POST("/muses-rest/java/rest/viewlogistics/"+CHANEL)
    Observable<HttpResponseResult<LogisticsInfo>> getLogisticsInfo(@Body Map<String,Object> map);

开始请求:

 Map<String, Object> map = new HashMap<>();
 map.put("logisticsid", 20);
 map.put("logisticsno", "1000817443587");
 ServiceManager
         .getApiService()
   .getLogisticsInfo(map)
                        .compose(MainActivity.this.<HttpRespResult<LogisticsInfo>>bindToLifecycle())
                        .compose(TransformerHelper.<LogisticsInfo>transformer())
                        .compose(new DialogTransformer(MainActivity.this).<HttpRespResult<LogisticsInfo>>showDialog())
                        .subscribe(new CommonObserver<LogisticsInfo>() {
             @Override
             protected void onSuccess(LogisticsInfo logisticsInfo) {
                 Logger.e(logisticsInfo.toString());
             }
         });

List的请求:

    @POST("/muses-rest/java/rest/viewlogistics/"+CHANEL)
    Observable<HttpResponseResult<LogisticsInfo>> getLogisticsInfo(@Body Map<String,Object> map);

开始请求:

ServiceManager
        .getApiService()
        .testGet2()
      .compose(MainActivity.this.<HttpRespResult<List<String>>>bindToLifecycle())
                        .compose(TransformerHelper.<List<String>>transformer())
                        .compose(new DialogTransformer(MainActivity.this).<HttpRespResult<List<String>>>showDialog())
                        .subscribe(new CommonObserver<List<String>>() {
            @Override
            protected void onSuccess(List<String> stringList) {
                String[] str = stringList.toArray(new String[stringList.size()]);
                Logger.e(Arrays.toString(str));
            }
        });

注意三个 compose 操作符的顺序不要乱了,否则会出现异常。
其中

 .compose(MainActivity.this.<HttpResponseResult<List<String>>>bindToLifecycle())

是与当前的 Activity 进行绑定,Activity 需要继承 RxAppCompatActivity 或者 RxActivity ,如果已有自己的 BaseActivity,则让 BaseActivity 去继承即可。Fragment类似。

.compose(TransformerHelper.<List<String>>transformer())

是对请求结果进行处理,即从 HttpResponseResult 取出 T

 .compose(new DialogTransformer(MainActivity.this).<List<String>>showDialog())

是操作 ProgressDialog 的,其生命周期会伴随整个请求,不需要时可以不加。

一般在请求成功后会进行数据处理,而失败时则进行 Toast 提示用户,CommonObserver中已经对错误进行了处理,自动弹出 Toast,如果不需要弹出 Toast ,重写 CommonObserveronFailed(HttpResponseException responseException) 方法即可。如果需要针对不同的业务逻辑错误进行不同的处理,则使用 responseException.getStatus() 得到错误码进行处理即可。

非 Restful 接口

由于非 Restful 接口用的可能比较少,所以没对其进行整理,只提供了一个实现,当然,如果项目中非 Restful 接口用的比较多的话还是封装一下比较好。

ServiceManager
       .getApiService()
       .testGet1()
       .compose(SchedulerTransformer.<String>transformer())//线程转换
       .compose(MainActivity.this.<String>bindToLifecycle())//绑定生命周期,防止内存泄露
       .compose(new DialogTransformer(MainActivity.this).<String>transformer())//progressDialog
       .subscribe(new Observer<String>() {
           @Override
           public void onSubscribe(Disposable d) {
           }
           @Override
           public void onNext(String s) {
               Logger.e(s);
           }
           @Override
           public void onError(Throwable e) {
               Logger.e(e.toString());
           }
           @Override
           public void onComplete() {
           }
       });

下载操作

 final DownloadHelper downloadHelper = new DownloadHelper(url, dirPath, fileName);

        downloadHelper.downloadFile(new DownloadListener() {
            @Override
            public void update(long bytesRead, long contentLength) {
                Logger.e("----bytesRead=" + bytesRead);
                Logger.e("----contentLength=" + contentLength);
                progressDialog.setProgress((int) ((100 * bytesRead) / contentLength));
            }

            @Override
            public void onSuccess(File file) {
                progressDialog.cancel();
                Logger.e(file.getAbsolutePath() + "----" + file.length());
            }

            @Override
            public void onFailure(Throwable t) {
                progressDialog.cancel();
                Logger.e("----" + t.toString());
            }
        });

取消下载

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,284评论 25 707
  • 前言RxJava和Retrofit也火了一段时间了,不过最近一直在学习ReactNative和Node相关的姿势,...
    AFinalStone阅读 530评论 0 0
  • 前言 RxJava和Retrofit也火了一段时间了,不过最近一直在学习ReactNative和Node相关的姿势...
    流水潺湲阅读 1,221评论 3 6
  • 这夜的黑 榨出思恋的液汁 渗入千疮百孔的干涸 满山的红叶 可是你微笑的音符 捎来春天的潮汐 你涉水而去 没留下一瓣...
    荒山小调阅读 198评论 0 0
  • 1. 感恩妈妈为我们准备素食,让全家人吃素。 2. 感恩朋友请吃夜宵。 3. 感恩妈妈陪我在大年初一一起去参加发展...
    诗羚阅读 299评论 0 1