1. 程式人生 > >安卓輪子之Retrofit原始碼賞析

安卓輪子之Retrofit原始碼賞析

Retrofit 中 Service 介面的實現

對於自定義 Service 類:

public interface GithubService {
    @GET("users/{user}/repos")
    MyCall<String> listRepos(@Path("user") String user);
}

使用時:

GithubService githubService = retrofit.create(GithubService.class);
MyCall<String> call = githubService.listRepos
("xiangaoole");

我們看一下 create 原始碼:

// Retrofit.java
@SuppressWarnings("unchecked")
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 { // 呼叫的是 Object 方法 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); } }); }

create() 方法最終返回的就是 GithubService 介面的代理。在呼叫 listRepos() 方法時,loadServiceMethod() 方法載入一個 ServiceMethod 物件,在建立過程中完成對介面方法的解析,也就是解析方法註解,同時從 retrofit 的 CallAdapterFactory 集合和 ConverterFactory 集合中選擇型別匹配的儲存在成員變數 callAdapter 和 responseConverter 中。最後呼叫 callAdapter 的 adapt(Call call) 方法來執行 OkHttpCall。

這裡的 callAdapter 是從 retrofit 物件的 CallAdapterFactory 集合中找到和介面方法的返回值匹配的元素,進而建立的 CallAdapter 例項。

沒有設定 CallAdapterFactory 時,預設的 callAdapter 是 ExecutorCallAdapter,執行 adapt() 方法返回物件型別為 ExecutorCallbackCall。

我們的例子中,設定了自定義的 MyCallAdapter.Factory,動態代理呼叫 listRepo 方法時,最終呼叫 MyCallAdapter 的 adapt(Call call) 方法,返回我們自定義的 MyCall 物件。

網路請求的傳送

預設CallAdapter

沒有新增自定義 CallAdapter.Factory 時,採用預設的 ExecutorCallbackCall 傳送網路請求。ExecutorCallbackCall 的 execute()enqueue() 方法,委託真實物件 retrofit2.OkHttpCall 來執行。

static final class ExecutorCallbackCall<T> implements Call<T> {
    final Executor callbackExecutor;
    final Call<T> delegate; // 真實物件

    ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
        this.callbackExecutor = callbackExecutor;
        this.delegate = delegate;
    }

    ...
}

同步提交:

@Override public Response<T> execute() throws IOException {
  return delegate.execute();
}

非同步提交:

@Override public void enqueue(final Callback<T> callback) {
  checkNotNull(callback, "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);
        }
      });
    }
  });
}

最後都會呼叫 parseResponse() 方法,呼叫 StringCallAdapter 的 adapt() 方法將 ResponseBody 轉化為 String。

// retrofit2.OKHttpCall
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ...
    T body = serviceMethod.toResponse(catchingBody);
    ...
}

// retrofit2.ServiceMethod<R, T>
R toResponse(ResponseBody body) throws IOException {
  return responseConverter.convert(body);
}