Retrofit+RxJava總結

ElviraCowle 8年前發布 | 13K 次閱讀 Retrofit RxJava

上次發布的文章 Retrofit2.0+RxJava初步 簡單介紹了Retrofit2.0與RxJava結合使用, 前段時間在公司的項目中引入了Retrofit框架,今天對項目中碰到的問題和一些常見的使用場景做個總結。

本文主要包含以下2個內容:

  • HttpResult統一處理返回結果
  • 網絡請求與生命周期綁定
  • retrofit緩存及日志

統一處理返回結果

在項目中一般與后臺定義好返回的json數據結構, 我們的格式如下:

{
    "code": 0,
    "data": ...,
    "msg": "success"
}

所以,在項目的service層中,統一判斷code值, 如果錯誤, 拋出異常, 如果正確,再把data結構返回給上層界面層處理。

首先,定義一個HttpResult對象:

public class HttpResult<T> {
    public int code;
    public String msg;
    public T data;
}

第二步, 我們在上一篇文章可以看到, 定義一個請求的方法如下:

@GET("shots/{id}/comments")
Observable<HttpResult<Comments>> getComments(@Path("id") int id, @Query("page") String page);

對于如何將HttpResult對象,進行解析,成功的話傳回Comments結構, 失敗則拋出異常進行處理。

這里需要用到RxJava的一個功能: map() , 它是RxJava的一個核心功能之一, 這個方法提供了對事件序列進行變換的支持, 也就是說它可以將傳入的一個對象轉化成另外一個對象, 它的參數是一個“FunX”(x是數字,代表有幾個參數)。

例如想要實現HttpResult<T> --> T 的轉換, 我們是這樣實現的:

private class HttpResultFunc<T> implements Func1<HttpResult<T>, T> {

    @Override
    public T call(HttpResult<T> httpResult) {
        if (httpResult == null) {
            throw new HttpException(400, "網絡錯誤");
        } else if (!httpResult.isSuccess()) {
            String msg = httpResult.msg != null ? httpResult.msg : "未知錯誤";
            throw new HttpException(httpResult.code, msg);
        } else
            return httpResult.data;
    }
}

有了上面的轉化, 為了上面的轉化適用于所有的接口請求, 我們得將上述轉化用transform封裝起來, 然后使用compose將Observable自身進行變化, 代碼如下:

private final HttpResultFunc<Object> func = new HttpResultFunc<>();

private class RetrofitTransformer implements Transformer {

    @Override
    public Object call(Object o) {
        Observable observable = ((Observable) o);
        return observable.subscribeOn(io())
                .unsubscribeOn(io())
                .observeOn(AndroidSchedulers.mainThread())
                .onErrorReturn(errorFunc)
                .map(func);
    }
}

protected <T> Observable.Transformer<HttpResult<T>, T> lifts() {
    return (Observable.Transformer<HttpResult<T>, T>) transformer;
}

最后, 完成Observable的轉化:

return ApiService.getComments(id, page).compose(this.<Comments>lifts());

生命周期綁定

· 內存泄漏的問題

當我們在調用網絡請求的時候, 會生成一個subscription對象, 如果里面引用了context或者其他的view對象, 而在Activity生命周期結束的時候又沒有及時結束, 那么很容造成內存泄漏的問題。

這里用了CompositeSubscription解決這個問題:

mCompositeSubscription = new CompositeSubscription();

public void addSubscription(Subscription subscription) {
    if (mCompositeSubscription != null && mCompositeSubscription.isUnsubscribed()) {
        mCompositeSubscription.add(subscription);
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (mCompositeSubscription != null && !mCompositeSubscription.isUnsubscribed()) {
        mCompositeSubscription.unsubscribe();
        mCompositeSubscription = null;
    }
}

上述代碼在基類BaseActivity中實現, 每次調用網絡請求的時候,都通過addSubscription() 方法。

緩存及日志

retrofit緩存及日志功能網上代碼比較多了, 就簡單說一下,都是通過攔截器實現的 :

  • 緩存
    private static Interceptor cacheInterceptor = new Interceptor() {
      @Override
      public Response intercept(Chain chain) throws IOException {
          Request request = chain.request();
          if (!HttpUtils.isNetworkConnected()) {
              request = request.newBuilder()
                      .cacheControl(CacheControl.FORCE_CACHE)
                      .build();
          }
          Response response = chain.proceed(request);
          if(HttpUtils.isNetworkConnected()){
              //有網的時候讀接口上的@Headers里的配置
              String cacheControl = request.cacheControl().toString();
              return response.newBuilder()
                      .header("Cache-Control", cacheControl)
                      .removeHeader("Pragma")
                      .build();
          }else{
              return response.newBuilder()
                      .header("Cache-Control", "public, only-if-cached, max-stale=2419200")
                      .removeHeader("Pragma")
                      .build();
          }
      }
    };
    添加緩存攔截的時候, 最好用兩種方式都添加一下, 僅僅是addInterceptor是不夠的:
    .addNetworkInterceptor(cacheInterceptor)   
    .addInterceptor(cacheInterceptor)

 

 

來自:http://www.jianshu.com/p/fbc6848deffa

 

 本文由用戶 ElviraCowle 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!