Retrofit 2.4.0 工作流程源碼解析

本文參考 Retrofit分析-漂亮的解耦套路
圖片來源 Retrofit分析-漂亮的解耦套路
源碼版本:Retrofit2.4.0 Rxjava2 2.2.0

Refrofit流程圖

Retrofit原理

我們根據(jù)這張流程圖來對著源碼慢慢來看。一切從左上角開始。

1.retrofit.create(service.class)

  public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.adapt(okHttpCall);
          }
        });
  }

這里主要用到了JDK的動態(tài)代理功能。實現(xiàn)InvocationHandler接口即可。通過loadServiceMethod()代理生成傳入Service的代理類ServiceMethod。下方的OkHttpCall是OKhttp3的封裝類。最后通過serviceMethod.adapt(okHttpCall)將okHttpCall設(shè)置回serviceMethod中,以便之后在各種CallAdapter中使用。callAdapter是一個適配器,適配成其他平臺可以使用的類型,比如轉(zhuǎn)化為Rxjava或者Rxjava2。

    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

這里回頭再看下loadServiceMethod()方法,他設(shè)置了緩存池,自身是通過ServiceMethod.Builder()建造者來生成,此方法將收集傳入的service方法包含的注解信息以及在Retrofit.Builder()方法中配置的BaseUrl,okHttpClient,Converter,CallAdapter并將其轉(zhuǎn)化為參數(shù)設(shè)置到result中。此時我們傳入的service中所有數(shù)據(jù)都已經(jīng)裝配完畢了。此時上圖中我們已經(jīng)進行到了圖中CallAdapter.adapt。由上述代碼我們可知retrofit.create({service}).{service.method}.實際調(diào)用的是callAdapter.adapt(call)。

2.CallAdapter.adapt(call)

CallAdapter實現(xiàn)類

完成了以上配置工作,接下來就要開始動手干活了。CallAdapter有四個實現(xiàn)類,以現(xiàn)在的最常用的Rxjava2.2.0 + Retrofit2.4.0模式為例,所以最終調(diào)用的是RxJava2CallAdapter中的adapt方法。(當(dāng)然RxJava2CallAdapter在頂部圖片是已經(jīng)沒有了)

 @Override public Object adapt(Call<R> call) {
    Observable<Response<R>> responseObservable = isAsync
        ? new CallEnqueueObservable<>(call)
        : new CallExecuteObservable<>(call);
   ...
  }

上述代碼中CallEnqueueObservable與CallExecuteObservable對應(yīng)Okhttp中的異步請求和同步請求。這里通過RxJava2CallAdapterFactory.create()/createAsync()去設(shè)置,本質(zhì)是改變Okhttp請求方法來控制同步異步,但是現(xiàn)在很多做法是通過Rxjava2去調(diào)度使用的時候去調(diào)度線程,所以可以看到很多庫封裝Retrofit是使用RxJava2CallAdapterFactory.create()的。但是我們這里還是著重看下異步請求。

3.CallEnqueueObservable

final class CallEnqueueObservable<T> extends Observable<Response<T>> {
....
  @Override protected void subscribeActual(Observer<? super Response<T>> observer) {
    // Since Call is a one-shot type, clone it for each new observer.
    Call<T> call = originalCall.clone();
    CallCallback<T> callback = new CallCallback<>(call, observer);
    observer.onSubscribe(callback);
    call.enqueue(callback);
  }
private static final class CallCallback<T> implements Disposable, Callback<T> {
....
    CallCallback(Call<?> call, Observer<? super Response<T>> observer) {
      this.call = call;
      this.observer = observer;
    }

    @Override public void onResponse(Call<T> call, Response<T> response) {
      if (call.isCanceled()) return;
      try {
        observer.onNext(response);
        if (!call.isCanceled()) {
          terminated = true;
          observer.onComplete();
        }
      } catch (Throwable t) {
      ....
          }
        }
      }
    }

    @Override public void onFailure(Call<T> call, Throwable t) {
   ....
    }
...
}

CallEnqueueObservable重寫了subscribeActual,subscribeActual會在subscribe中調(diào)用。其中CallCallback是連接Retrofit,Rxjava2,OKhttp的橋梁,Okhttp產(chǎn)生回調(diào)后會傳回Retrofit,最終通知Rxjava2。這里也走到了最終網(wǎng)絡(luò)請求的方法call.enqueue(callback),點進去我們就可以看到熟悉的OKHttp的網(wǎng)絡(luò)方法。

4.call.enqueue(new okhttp3.Callback()

 call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
        Response<T> response;
        try {
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }

        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        callFailure(e);
      }

      private void callFailure(Throwable e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
    });
  }

在call.enqueue中還看到中callback.onResponse(OkHttpCall.this, response)callback.onFailure(OkHttpCall.this, e)此處的callback就是observer.onSubscribe(callback)中設(shè)置的callback,就此回到Retrofit的回調(diào)。在CallCallback.onResponse中又有observer.onNext(response)最后回到了Rxjava2。至此流程結(jié)束。接下來就全部是Rxjava2的事兒了。

5.總結(jié)

Retrofit2在靈活解耦方面做的十分精妙,需要多看幾次學(xué)習(xí)學(xué)習(xí)其中的思想。如果文章中描述有誤,歡迎在留言中指出。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容