三默网为您带来有关“RxJava2 和 Retrofit2 的封装和使用”的文章内容,供您阅读参考。

RxJava2 和 Retrofit2 的封装和使用

2023-01-21 19:17:15

根据 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();