Retrofit源碼解析:RxJavaCallAdapterFactory

尊重他人的勞動成果,轉載請標明出處:http://blog.csdn.net/gengqiquan/article/details/52785773, 本文出自:【gengqiquan的博客】

上篇博客Retrofit源碼解析我們講到了retrofit所採用的註解方法會交由ServiceMethod的callAdapter 去進行層層適配,然後交由OkHttpCall 去執行具體的請求 並且這個callAdapter 是可以設置的。使用rxjava的用戶一般會設置RxJavaCallAdapterFactory.create())而如果用戶如果不設置的話,retrofit會默認創建一個。

創建過程就在之前的retrofit的build()方法裏

  Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

可以看到採用的是默認的ExecutorCallAdapterFactory,這個適配工廠比較簡單,就是直接把用回調傳遞響應結果

@Override
  public CallAdapter<Call<?>> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter<Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public <R> Call<R> adapt(Call<R> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }

他的adapt方法裏構建了一個回調執行器

    @Override public void enqueue(final Callback<T> callback) {
      if (callback == null) throw new NullPointerException("callback == null");

      delegate.enqueue(new Callback<T>() {
        @Override public void onResponse(Call<T> call, final Response<T> response) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              if (delegate.isCanceled()) {
                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
              } else {
                callback.onResponse(ExecutorCallbackCall.this, response);
              }
            }
          });
        }

        @Override public void onFailure(Call<T> call, final Throwable t) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              callback.onFailure(ExecutorCallbackCall.this, t);
            }
          });
        }
      });
    }

  //這裏省略了一大批代理實際請求的方法
    }

可以看到實際請求成功後會傳給callbackExecutor自身的回調,這個套路和我們正常封裝網絡請求的套路一樣,多包裹一層回調,再利用靜態代理調用實際請求的回調方法,將結果傳遞給自己的回調,好處是所有自己實現的解析類都只需要按照這個套路來就可以了,而不需要去關注實際call執行的內部邏輯。並且框架使用者也無法去幹預框架內部的邏輯,解耦的相當徹底,這算是第二道菜吧。

上面是retrofit框架自帶的解析類,下面我們來看看基於rxjava實現的解析類,retrofit作爲一個網絡框架而言,全面而強大自不用多說,但他真正吸引我和許多開發者卻是他與rxjava的無縫對接。那麼如果我們搞清楚這個無縫對接的過程,是不是就可以不用retrofit而讓自己原本的網絡框架也實現和retrofit的無縫對接呢?答案是肯定的。

 @Override
  public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
  //省略一堆代碼
    if (isCompletable) {
      // Add Completable-converter wrapper from a separate class. This defers classloading such that
      // regular Observable operation can be leveraged without relying on this unstable RxJava API.
      // Note that this has to be done separately since Completable doesn't have a parametrized
      // type.
      return CompletableHelper.createCallAdapter(scheduler);
    }

    CallAdapter<Observable<?>> callAdapter = getCallAdapter(returnType, scheduler);
    if (isSingle) {
      // Add Single-converter wrapper from a separate class. This defers classloading such that
      // regular Observable operation can be leveraged without relying on this unstable RxJava API.
      return SingleHelper.makeSingle(callAdapter);
    }
    return callAdapter;
  }

三種返回,我們看第二種

private CallAdapter<Observable<?>> getCallAdapter(Type returnType, Scheduler scheduler) {
    Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
    Class<?> rawObservableType = getRawType(observableType);
    if (rawObservableType == Response.class) {
      if (!(observableType instanceof ParameterizedType)) {
        throw new IllegalStateException("Response must be parameterized"
            + " as Response<Foo> or Response<? extends Foo>");
      }
      Type responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
      return new ResponseCallAdapter(responseType, scheduler);
    }

    if (rawObservableType == Result.class) {
      if (!(observableType instanceof ParameterizedType)) {
        throw new IllegalStateException("Result must be parameterized"
            + " as Result<Foo> or Result<? extends Foo>");
      }
      Type responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
      return new ResultCallAdapter(responseType, scheduler);
    }

    return new SimpleCallAdapter(observableType, scheduler);
  }

依舊三種返回,每種callAdapter的實現裏都實現了adapt,也就是我們retrofit代理的那個方法,我們隨便看一個,其實思路是一樣的,都是通過rxjava的創建操作符創建Observable

static final class ResultCallAdapter implements CallAdapter<Observable<?>> {
    private final Type responseType;
    private final Scheduler scheduler;

    ResultCallAdapter(Type responseType, Scheduler scheduler) {
      this.responseType = responseType;
      this.scheduler = scheduler;
    }

    @Override public Type responseType() {
      return responseType;
    }

    @Override public <R> Observable<Result<R>> adapt(Call<R> call) {
      Observable<Result<R>> observable = Observable.create(new CallOnSubscribe<>(call)) //
          .map(new Func1<Response<R>, Result<R>>() {
            @Override public Result<R> call(Response<R> response) {
              return Result.response(response);
            }
          }).onErrorReturn(new Func1<Throwable, Result<R>>() {
            @Override public Result<R> call(Throwable throwable) {
              return Result.error(throwable);
            }
          });
      if (scheduler != null) {
        return observable.subscribeOn(scheduler);
      }
      return observable;
    }
  }

通過map轉換符把call的response轉換回了自定義的Result的response,然後在恰當的地方將Observable傳遞下去,然後我們就可以在請求執行成功後拿到框架返回給我們的Observable開心的進行操作了。
以上就是RxJavaCallAdapterFactory做的事了

關於ConverterFactory,其實裏面東西更少就是把返回的值轉換爲我們設定的對象類型。通過Retrofit自定義Converter之StringConverterFactory應該可以看出來ConverterFactory的一般實現套路了。

對了,本人收藏了一份詳細的rxjava教程。嘿嘿,想要的可以到羣裏要。

我建了一個QQ羣(羣號:121606151),用於大家討論交流Android技術問題,有興趣的可以加下,大家一起進步。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章