Retrofit 2.0源碼解析

簡介

剛接觸Retrofit的時候,就寫了一篇簡單的使用介紹:Retrofit 2.0基本使用方法,算是對Retrofit的基礎入門。也算是接觸Retrofit一段時間了,現在差不多可以對源碼層進行解析,最起碼,理解原理后可以使得我們使用起來更加得心應手 _

網絡請求使用基本方法

參考官網:

Introduction

Retrofit turns your HTTP API into a Java interface.

public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}

The Retrofit class generates an implementation of the GitHubService interface.

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();
GitHubService service = retrofit.create(GitHubService.class);

Each Call from the created GitHubService can make a synchronous or asynchronous HTTP request to the remote webserver.

Call<List<Repo>> repos = service.listRepos("octocat");
//synchronous request
repos.execute();
//asynchronous request
repos.enqueue(new Callback<ResponseBody>() {/***/});

Use annotations to describe the HTTP request:

URL parameter replacement and query parameter support
Object conversion to request body (e.g., JSON, protocol buffers)
Multipart request body and file upload

源碼解析: retrofit:2.3.0

從上一節的使用Retrofit進行網絡請求中,我們可以看到,請求過程主要分為以下幾步:

  1. 創建一個接口進行HTTP請求描述;
  2. 使用Retrofit.Builder構建模式構造出一個Retrofit實例;
  3. 調用retrofit.create()方法獲取請求接口實例;
  4. 由請求接口實例獲取到Call對象;
  5. 進行網絡請求(同步/異步)

接下來,我們就按照以上正常的網絡請求順序來對Retrofit源碼進行解析。

  • 創建一個接口進行HTTP請求描述
public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}

這里主要做的就是采用注解的方式進行HTTP描述,后面在第4步由請求接口實例獲取到Call對象時進行反射提取注解內容進行HTTP請求構造(如果開啟了預先加載解析(validateEagerly=true),那么在第3步調用retrofit.create()方法獲取請求接口實例的時候就會進行注解解析),具體解析方法參考后續分析。

  • 使用Retrofit.Builder構建模式構造出一個Retrofit實例
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();

那我們就先來看下Retrofit.Builder部分源碼:

  /**
     * Build a new {@link Retrofit}.
     * <p>
     * Calling {@link #baseUrl} is required before calling {@link #build()}. All other methods
     * are optional.
     */
    public static final class Builder {
        private final Platform platform;
        //callFactory通過newCall(Request request)方法,返回一個okhttp3.Call對象,以便讓我們進行實際的HTTP請求
        //也就是說callFactory是我們用來生成一個客戶端HTTP請求工廠實例
        private @Nullable okhttp3.Call.Factory callFactory;
        private HttpUrl baseUrl;
        //converterFactories生產Converter<F, T>,用于將HTTP返回結果F類型轉換為T類型,或將HTTP請求類型F轉換為T。
        private final List<Converter.Factory> converterFactories = new ArrayList<>();
        //adapterFactories生產 CallAdapter<R, T>,用于將retrofit2.Call<R>網絡請求類型轉換為T類型:T adapt(Call<R> var1);
        private final List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
        private @Nullable
        Executor callbackExecutor;
        private boolean validateEagerly;
        ···
        ···
        ···
}

Retrofit.Builder的注釋中,我們可以看到,在調用Retrofit.Builder.build()之前,除了baseUrl()是必須配置的以外,其他的內容都是可選配置。
這里要對兩個類型做下講解,因為筆者在剛分析Retrofit源碼時,被這兩個類型的概念弄得頭暈眼脹,好在一頓分析后,終于有了一點眉目,這兩個類型就是:Converter<F, T>CallAdapter<R, T>

  • Converter<F, T>:數據轉換器,用來將HTTP請求返回結果由F類型轉換為T類型,或者將HTTP請求類型F轉換為T
/**
 * Convert objects to and from their representation in HTTP. Instances are created by {@linkplain
 * Factory a factory} which is {@linkplain Retrofit.Builder#addConverterFactory(Factory) installed}
 * into the {@link Retrofit} instance.
 */
public interface Converter<F, T> {
  T convert(F value) throws IOException;
          ···
          ···
          ···
}

舉例:

new Retrofit.Builder()
                .baseUrl("https://api.github.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();

上面配置了ConverterFactoryGsonConverterFactory,那么當HTTP請求結果返回時,就會由GsonConverterFactory產生的Converter,假設為Converter<ResponseBody, List<Repo>>,該Converter就會將HTTP返回結果ResponseBody轉換為 List<Repo>
而若是將對象轉換為數據,那么假設類型為:Converter< List<Repo>, RequestBody>,該Converter在構建請求體時,會將List<Repo>轉換為RequestBody對象。

  • CallAdapter<R, T>:請求適配器,用于將retrofit2.Call<R>網絡請求類型轉換為T類型
/**
 * Adapts a {@link Call} with response type {@code R} into the type of {@code T}. Instances are
 * created by {@linkplain Factory a factory} which is
 * {@linkplain Retrofit.Builder#addCallAdapterFactory(Factory) installed} into the {@link Retrofit}
 * instance.
 */
public interface CallAdapter<R, T> {
  /**
   * Returns the value type that this adapter uses when converting the HTTP response body to a Java
   * object. For example, the response type for {@code Call<Repo>} is {@code Repo}. This type
   * is used to prepare the {@code call} passed to {@code #adapt}.
   * <p>
   * Note: This is typically not the same type as the {@code returnType} provided to this call
   * adapter's factory.
   */
  Type responseType();

  /**
   * Returns an instance of {@code T} which delegates to {@code call}.
   * <p>
   * For example, given an instance for a hypothetical utility, {@code Async}, this instance would
   * return a new {@code Async<R>} which invoked {@code call} when run.
   * <pre><code>
   * @Override
   * public <R> Async<R> adapt(final Call<R> call) {
   *   return Async.create(new Callable<Response<R>>() {
   *     @Override
   *     public Response<R> call() throws Exception {
   *       return call.execute();
   *     }
   *   });
   * }
   * </code></pre>
   */
  T adapt(Call<R> call);
  /**
   * Creates {@link CallAdapter} instances based on the return type of {@linkplain
   * Retrofit#create(Class) the service interface} methods.
   */
              ···
              ···
              ···
}

舉例:

new Retrofit.Builder()
                .baseUrl("https://api.github.com/")      
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();

上面配置了CallAdapterFactoryRxJava2CallAdapterFactory,這里的作用就是將Retrofit2.Call<T>對象轉換為Observable<T>類型,所以如果配置了RxJava2CallAdapterFactory,那么接口方法聲明應該改為如下形式:

public interface GitHubService {
    @GET("users/{user}/repos")
    Observable<List<Repo>> listRepos(@Path("user") String user);
}

其實這個addCallAdapterFactory實現原理是挺簡單的,因為Retrofit里面維護了CallAdapter.Factory一個數組,在使用Builder配置的時候,所有配置的CallAdapter.Factory最后都會保存到Retrofit那個數組中,后面在進行轉換是,Retrofit會根據接口方法返回結果類型(此處為:Observable<List<Repo>>),遍歷CallAdapter.Factory數組,找到一個能處理該返回類型的CallAdapter后,就不再遍歷。更多具體的解析方法請參考后續整體流程的介紹。

上面講了那么多的東西,可是還是沒有講到Retrofit實例的創建,別著急,在查看Retrofit.Builder.build()方法前,我們還要看下Builder的構造函數:

        Builder(Platform platform) {
            this.platform = platform;
            // Add the built-in converter factory first. This prevents overriding its behavior but also
            // ensures correct behavior when using converters that consume all types.
            converterFactories.add(new BuiltInConverters());
        }

        public Builder() {
            this(Platform.get());
        }

當我們調用:

new Retrofit.Builder()
                .baseUrl("https://api.github.com/")
                .build();

就會走入:Builder()--> Builder(Platform platform)
然后我們看到,在Builder(Platform platform)構造函數里面,會往converterFactories里面添加進一個BuiltInConverters對象,所以默認的ConverterFactory就是BuiltInConverters。前面說過ConverterFactory主要是用來將HTTP返回結果進行類型轉換或者將HTTP請求體進行類型轉換,然后我們看下BuiltInConverters是怎樣的轉換方式:

final class BuiltInConverters extends Converter.Factory {
  //返回結果轉換
  @Override
  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    if (type == ResponseBody.class) {
      //如果annotations是Streaming類型
      return Utils.isAnnotationPresent(annotations, Streaming.class)
          ? StreamingResponseBodyConverter.INSTANCE
          : BufferingResponseBodyConverter.INSTANCE;
    }
    if (type == Void.class) {
      return VoidResponseBodyConverter.INSTANCE;
    }
    return null;
  }

  //請求轉換
  @Override
  public Converter<?, RequestBody> requestBodyConverter(Type type,
      Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
    if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) {
      return RequestBodyConverter.INSTANCE;
    }
    return null;
  }

  static final class VoidResponseBodyConverter implements Converter<ResponseBody, Void> {
    static final VoidResponseBodyConverter INSTANCE = new VoidResponseBodyConverter();

    @Override public Void convert(ResponseBody value) throws IOException {
      value.close();
      return null;
    }
  }

  static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> {
    static final RequestBodyConverter INSTANCE = new RequestBodyConverter();

    @Override public RequestBody convert(RequestBody value) throws IOException {
      return value;
    }
  }

  static final class StreamingResponseBodyConverter
      implements Converter<ResponseBody, ResponseBody> {
    static final StreamingResponseBodyConverter INSTANCE = new StreamingResponseBodyConverter();

    @Override public ResponseBody convert(ResponseBody value) throws IOException {
      return value;
    }
  }

  static final class BufferingResponseBodyConverter
      implements Converter<ResponseBody, ResponseBody> {
    static final BufferingResponseBodyConverter INSTANCE = new BufferingResponseBodyConverter();

    @Override public ResponseBody convert(ResponseBody value) throws IOException {
      try {
        // Buffer the entire body to avoid future I/O.
        return Utils.buffer(value);
      } finally {
        value.close();
      }
    }
  }

  static final class ToStringConverter implements Converter<Object, String> {
    static final ToStringConverter INSTANCE = new ToStringConverter();

    @Override public String convert(Object value) {
      return value.toString();
    }
  }
}

返回結果轉換的時候,有3種情況:

  • 如果返回類型是ResponseBody類型,那么可能返回的是:StreamingResponseBodyConverter.INSTANCE或者BufferingResponseBodyConverter.INSTANCE,再跟蹤進去這兩個類里面的convert函數:
 @Override public ResponseBody convert(ResponseBody value){···}

發現傳入的是ResponseBody,返回的也是ResponseBodyBufferingResponseBodyConverter里面有進行特殊處理,主要是為了去除future I/O),所以我們可以認為BuiltInConverters對HTTP返回結果沒有進行轉換處理。

  • 如果返回類型是Void類型,那么最終就將ResponseBody資源關閉后,直接返回null
  • 如果返回類型不是ResponseBodyVoid類型,直接返回null

同理,我們來看下請求體轉換:

//請求轉換
  @Override
  public Converter<?, RequestBody> requestBodyConverter(Type type,
      Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
    if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) {
      return RequestBodyConverter.INSTANCE;
    }
    return null;
  }
static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> {
    static final RequestBodyConverter INSTANCE = new RequestBodyConverter();

    @Override public RequestBody convert(RequestBody value) throws IOException {
      return value;
    }
  }

可以看到,如果是RequestBody類型,那就不轉換,如果不是RequestBody類型,直接返回null

綜上所述:BuiltInConverters只能響應ResponseBodyRequestBody,但是并不進行任何轉換.對于其他類型,統統返回null。

到這里,終于可以走進Retrofit.Builder.build()函數,一窺究竟:

 /**
         * Create the {@link Retrofit} instance using the configured values.
         * <p>
         * Note: If neither {@link #client} nor {@link #callFactory} is called a default {@link
         * OkHttpClient} will be created and used.
         */
        public Retrofit build() {
            if (baseUrl == null) {
                throw new IllegalStateException("Base URL required.");
            }

            okhttp3.Call.Factory callFactory = this.callFactory;
            if (callFactory == null) {
                //callFactory默認為OkHttpClient
                callFactory = new OkHttpClient();
            }

            Executor callbackExecutor = this.callbackExecutor;
            if (callbackExecutor == null) {
                //默認的callbackExecutor為Platform.Android.MainThreadExecutor
                //MainThreadExecutor繼承Executor,并復寫execute(Runnable r),
                // execute內部直接通過主線程Handler.post(r),即r.run發生在主線程
                callbackExecutor = platform.defaultCallbackExecutor();
            }

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

            // Make a defensive copy of the converters.
            //BuiltInConverters在Retrofit.Builder(Platform)構造時,已被傳入
            List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

            return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
                    callbackExecutor, validateEagerly);
        }

build函數一進去,就看到:

if (baseUrl == null) {
                throw new IllegalStateException("Base URL required.");
            }

這說明baseUrl是一定要進行配置的,否則程序就會拋出異常,這跟我們上面講到的一致。
接著往下看:

     okhttp3.Call.Factory callFactory = this.callFactory;
            if (callFactory == null) {
                //callFactory默認為OkHttpClient
                callFactory = new OkHttpClient();
            }

            Executor callbackExecutor = this.callbackExecutor;
            if (callbackExecutor == null) {
                //默認的callbackExecutor為Platform.Android.MainThreadExecutor
                //MainThreadExecutor繼承Executor,并復寫execute(Runnable r),
                // execute內部直接通過主線程Handler.post(r),即r.run發生在主線程
                callbackExecutor = platform.defaultCallbackExecutor();
            }

這里可以看到,如果沒有配置okhttp3.Call.Factory,那么就會使用默認的HTTP工廠類:OkHttpClient,用于客戶端程序創建okhttp3.Call對象,以進行實際的HTTP網絡請求。
如果沒有線程調度器callbackExecutor,那么就會使用默認的線程調度器:Platform.Android.MainThreadExecutor

  static class Android extends Platform {
        @Override
        public Executor defaultCallbackExecutor() {
            return new MainThreadExecutor();
        }

        @Override
        CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
            if (callbackExecutor == null) throw new AssertionError();
            return new ExecutorCallAdapterFactory(callbackExecutor);
        }

        static class MainThreadExecutor implements Executor {
            private final Handler handler = new Handler(Looper.getMainLooper());

            @Override
            public void execute(Runnable r) {
                handler.post(r);
            }
        }
    }

從源碼可以看出,默認的線程調度器是主線程調度器。
接下來再看:

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

可以看到,這里為adapterFactories增加了一個CallAdapterFactory:

//Platform.java
 CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
        if (callbackExecutor != null) {
            return new ExecutorCallAdapterFactory(callbackExecutor);
        }
        return DefaultCallAdapterFactory.INSTANCE;
    }
//ExecutorCallAdapterFactory.java
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
    final Executor callbackExecutor;

    ExecutorCallAdapterFactory(Executor callbackExecutor) {
        this.callbackExecutor = callbackExecutor;
    }

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

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

    static final class ExecutorCallbackCall<T> implements retrofit2.Call<T> {
        final Executor callbackExecutor;
        //HTTP請求委托類
        final retrofit2.Call<T> delegate;

        ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
            this.callbackExecutor = callbackExecutor;
            this.delegate = delegate;
        }
        //異步請求
        @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);
                        }
                    });
                }
            });
        }
        //同步請求
        @Override
        public Response<T> execute() throws IOException {
            return delegate.execute();
        }
       ···
      ···
      ···
}

在Android平臺上,callbackExecutor默認不為null,所以defaultCallAdapterFactory返回的是ExecutorCallAdapterFactory。從ExecutorCallAdapterFactoryget函數,可以看到,ExecutorCallAdapterFactory只會響應返回類型為Call的函數聲明(所以,如果我們沒有配置addCallAdapterFactory(),那么我們接口函數聲明的返回類型必須為Call<?>),響應處理的最終結果就是返回一個CallAdapter,這個CallAdapteradapt()函數會傳入一個HTTP請求委托類,然后返回一個HTTP請求代理類:ExecutorCallbackCall<T> implements retrofit2.Call<T>,這個代理類代理了委托類的異步HTTP網絡請求,并將返回結果通過線程調度器將回調監聽函數分發到具體線程上執行(默認線程調度器是主線程調度)。

講到這里,Retrofit實例的配置創建就算是完成了。下面這個圖展示了Retrofit.Builder提供的配置選項:

Builder

  • 調用retrofit.create()方法獲取請求接口實例
GitHubService service = retrofit.create(GitHubService.class);

那我們接下來就看一下create()的源碼:

 @SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
    public <T> T create(final Class<T> service) {
        //1.是否是接口
        //2.不能繼承其他接口
        Utils.validateServiceInterface(service);
        //預先加載解析注解:loadServiceMethod
        //默認false,即調用接口方法后,才進行解析
        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);
                        }
                        //java8平臺使用
                        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.callAdapter.adapt(okHttpCall);
                    }
                });
    }

這里我們可以看到,create方法返回的是一個 (T) Proxy.newProxyInstance()方法產生的一個動態代理對象(如果不清楚動態代理,可以看下我之前寫的文章:Java代理模式,里面對java的動態代理有詳細講解)。使用該動態代理對象進行方法調用后,會自動被InvocationHandler攔截,最終進入InvocationHandlerinvoke函數里面。

  • 由請求接口實例獲取到Call對象
Call<List<Repo>> repos = service.listRepos("octocat")

從上面create的分析中,我們知道,此處的service是一個動態代理類對象,所以,在調用方法時,會被InvocationHandlerinvoke方法攔截,所以調用:service.listRepos("octocat")就會進入InvocationHandler.invoke()中,查看下invoke函數,最主要的操作就是如下3句話:

 ServiceMethod<Object, Object> serviceMethod =
                                (ServiceMethod<Object, Object>) loadServiceMethod(method);
                        OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
                        return serviceMethod.callAdapter.adapt(okHttpCall);

ServiceMethodRetrofit中是一個很重要的類,主要做的就是對接口方法注解進行解析,最終生成一個Request

那我們先來看下loadServiceMethod()源碼:

ServiceMethod<?, ?> loadServiceMethod(Method method) {
        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;
    }

serviceMethodCache是一個緩存容器,是對接口方法的解析緩存。

//class Retrofit 
    private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();

loadServiceMethod()中可以看到,ServiceMethod的實例也是通過builder模式進行構建的,構建過程需傳入Retrofit對象和Method對象。

Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      //取得接口方法的注解
      this.methodAnnotations = method.getAnnotations();
      //返回接口方法參數類型
      this.parameterTypes = method.getGenericParameterTypes();
      //返回接口方法各個參數注解
      //按參數聲明順序排列,每個參數可能有多個注解,故二維數組
      //parameterAnnotationsArray[0][i]:第一個參數第i個注解
      //parameterAnnotationsArray[1][j]:第二個參數第j個注解
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

public ServiceMethod build() {
      //CallAdapter<T, R> callAdapter;適配Call的響應類型,將默認響應類型R轉換為類型T
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }
      //Converter<ResponseBody, T> responseConverter;HTTP交互中,轉換對象為數據 或 從數據轉換為對象
      responseConverter = createResponseConverter();

      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }
      ···
      ···

      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        if (Utils.hasUnresolvableType(parameterType)) {
          throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
              parameterType);
        }

        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        if (parameterAnnotations == null) {
          throw parameterError(p, "No Retrofit annotation found.");
        }

        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }
      ···
      ···
      return new ServiceMethod<>(this);
    }

ServiceMethod.Builder.build()源碼中可以看到:

callAdapter = createCallAdapter();

首先創建一個callAdapter,具體創建過程如下:

private CallAdapter<T, R> createCallAdapter() {
      //接口方法return類型
      Type returnType = method.getGenericReturnType();
     ···
      ···
      Annotation[] annotations = method.getAnnotations();
        //noinspection unchecked
      ···
      ···
        return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
    }

可以看到,其最終調用到的是retrofit.callAdapter()

  public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
        return nextCallAdapter(null, returnType, annotations);
    }

/**
     * Returns the {@link CallAdapter} for {@code returnType} from the available {@linkplain
     * #callAdapterFactories() factories} except {@code skipPast}.
     *
     * @throws IllegalArgumentException if no call adapter available for {@code type}.
     */
    public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
                                             Annotation[] annotations) {
        checkNotNull(returnType, "returnType == null");
        checkNotNull(annotations, "annotations == null");

        // final List<CallAdapter.Factory> adapterFactories;
        int start = adapterFactories.indexOf(skipPast) + 1;
        for (int i = start, count = adapterFactories.size(); i < count; i++) {
            CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
            if (adapter != null) {
                return adapter;
            }
        }

        //throw exception
       ···
        ···
    }

可以看到,createCallAdapter()就是從RetrofitList<CallAdapter.Factory> adapterFactories數組中,遍歷找到一個可以處理該接口方法返回類型和注解的CallAdapter<?, ?>。那根據我們之前的分析,如果我們沒有進行CallAdapter的配置,那么默認的CallAdapter就是ExecutorCallAdapterFactory.get(Call.class,xxx,retrofit);

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

                public Call<Object> adapt(Call<Object> call) {
                    return new ExecutorCallAdapterFactory.ExecutorCallbackCall(ExecutorCallAdapterFactory.this.callbackExecutor, call);
                }
            };
        }
    }

可以看到,默認的CallAdapter.Factory只會響應接口方法返回類型為Call,所以遍歷adapterFactories的時候,如果接口方法返回類型不是Call,那么ExecutorCallAdapterFactory.get()自然返回的就是null,然后就會繼續找下一個CallAdapterFactory,繼續嘗試,直到找到能處理該接口方法返回類型的CallAdapterFactory,由其返回一個CallAdapter

上面的流程可以這樣想(較為生動):
createCallAdapter說:retrofit,給我一個能處理我這個接口方法返回類型(假設為Observable<T>)的CallAdapter
retrofit接收到請求后,就會從自己的adapterFactories倉庫中一個一個的進行詢問:
首先找到默認的CallAdapter.Factory:ExecutorCallAdapterFactory,然后說:ExecutorCallAdapterFactory啊,你能處理Observable<T>這個返回類型嗎?
ExecutorCallAdapterFactory一看,說:retrofit啊,你給我的返回類型不是Call類型,我沒辦法處理,你找下一位CallAdapter.Factory仁兄吧。
既然默認的ExecutorCallAdapterFactory沒辦法處理這個接口方法返回類型,那retrofit就只能繼續問下一位CallAdapter.Factory啦,假設下一位是RxJava2CallAdapterFactory,然后,retrofit開始發問,說:RxJava2CallAdapterFactory仁兄呀,你能處理Observable<T>這個返回類型嗎?
RxJava2CallAdapterFactory一看,說:retrofit兄啊,你這個Observable<T>我拿手呀,隨隨便便進行處理,處理的結果拿到了這個CallAdapter,你趕緊拿著給createCallAdapter交差吧。
retrofit一聽,太高興了,說到:RxJava2CallAdapterFactory兄啊,您真牛逼,謝謝您了,好的好的,我趕緊拿著您給的CallAdaptercreateCallAdapter交差,那邊催的緊呢。
于是,retrofit高高興興地就往createCallAdapter那邊趕了,adapterFactories后面還沒問到的兄弟就不管了,沒辦法,哥(retrofit)時間緊,沒有那么多時間去一 一問候兄弟們,望兄弟們見諒 _

我們接著看ServiceMethod.Builder.build()方法,可以看到,createCallAdapter后,又createResponseConverter了:

 //Converter<ResponseBody, T> responseConverter;HTTP交互中,轉換對象為數據 或 從數據轉換為對象
      responseConverter = createResponseConverter();

responseConverterConverter<ResponseBody, T>類型,其實我們一看到這個,就應該大概知道是怎么做了,肯定又是跟retrofit請求,retrofit又從倉庫中進行查找,只是這回是從List<Converter.Factory> converterFactories中查找,直到找到一個能處理這種responseTypeConverter.Factory,由其返回一個Converter。讓我們看下源碼是不是這樣的:

//ServiceMethod.java
    private Converter<ResponseBody, T> createResponseConverter() {
      Annotation[] annotations = method.getAnnotations();
      try {
        return retrofit.responseBodyConverter(responseType, annotations);
      } catch (RuntimeException e) { // Wide exception range because factories are user code.
        throw methodError(e, "Unable to create converter for %s", responseType);
      }
    }
//Retrofit.java
 public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
        return nextResponseBodyConverter(null, type, annotations);
    }
   /**
     * Returns a {@link Converter} for {@link ResponseBody} to {@code type} from the available
     * {@linkplain #converterFactories() factories} except {@code skipPast}.
     *
     * @throws IllegalArgumentException if no converter available for {@code type}.
     */
    public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
            @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
        checkNotNull(type, "type == null");
        checkNotNull(annotations, "annotations == null");

        int start = converterFactories.indexOf(skipPast) + 1;
        for (int i = start, count = converterFactories.size(); i < count; i++) {
            Converter<ResponseBody, ?> converter =
                    converterFactories.get(i).responseBodyConverter(type, annotations, this);
            if (converter != null) {
                //noinspection unchecked
                return (Converter<ResponseBody, T>) converter;
            }
        }
        //throw exception
        ···
        ···
        ···
    }

可以看到,跟我們上面所說的過程是一樣的。
還記得嗎,有一個默認的retrofit2.Converter.Factory是:BuiltInConverters。那從BuiltInConverters得到的Converter<ResponseBody, T>是什么呢,根據我們之前的分析:

  • 如果responseTypeResponseBody類型,那么返回的還是ResponseBodyBufferingResponseBodyConverter有經過一些處理);
  • 如果responseTypeVoid類型,那么釋放ResponseBody資源,然后返回null;
  • 其他responseType類型,直接返回null

所以,如果我們沒有配置addConverterFactory,那么接口返回類型應該聲明為Call<ResponseBody>或者Call<Void>這類型的,這樣,默認的retrofit2.Converter.Factory才能進行處理

接著看Retrofit.Builder.build()方法,可以看到:

 for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }

這個是一個很重要的操作,就是對接口方法進行解析,追蹤進去再看下解析源碼:

 private void parseMethodAnnotation(Annotation annotation) {
      if (annotation instanceof DELETE) {
        parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
      } else if (annotation instanceof GET) {
        parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
      } else if (annotation instanceof HEAD) {
        parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
        if (!Void.class.equals(responseType)) {
          throw methodError("HEAD method must use Void as response type.");
        }
      } else if (annotation instanceof PATCH) {
        parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
      } else if (annotation instanceof POST) {
        parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
      } else if (annotation instanceof PUT) {
        parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
      } else if (annotation instanceof OPTIONS) {
        parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
      } else if (annotation instanceof HTTP) {
        HTTP http = (HTTP) annotation;
        parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
      } else if (annotation instanceof retrofit2.http.Headers) {
        String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
        if (headersToParse.length == 0) {
          throw methodError("@Headers annotation is empty.");
        }
        headers = parseHeaders(headersToParse);
      } else if (annotation instanceof Multipart) {
        if (isFormEncoded) {
          throw methodError("Only one encoding annotation is allowed.");
        }
        isMultipart = true;
      } else if (annotation instanceof FormUrlEncoded) {
        if (isMultipart) {
          throw methodError("Only one encoding annotation is allowed.");
        }
        isFormEncoded = true;
      }
    }

可以看到里面對很多方法都進行了解析,這里,我們就只拿GET方法解析源碼來分析下解析流程,其余方法解析都是類似的:

parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);

  private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
     ···
      ···
      ···
      this.relativeUrl = value;
      this.relativeUrlParamNames = parsePathParameters(value);
    }

按照官網那個例子,那么:this.relativeUrl = value = "users/{user}/repos",在parseHttpMethodAndPath最后,調用了 parsePathParameters(value)

/**
   * Gets the set of unique path parameters used in the given URI. If a parameter is used twice
   * in the URI, it will only show up once in the set.
   */
  static Set<String> parsePathParameters(String path) {
    Matcher m = PARAM_URL_REGEX.matcher(path);
    Set<String> patterns = new LinkedHashSet<>();
    while (m.find()) {
      patterns.add(m.group(1));
    }
    return patterns;
  }

這里采用正則表達式取出形如"{*}"這種結構的內容,保留在全局Set<String> relativeUrlParamNames集合里面。
像官網這個例子,當程序來到parsePathParameters("users/{user}/repos")的時候,正則表達式就獲得了user這個字符串,并存儲到全局relativeUrlParamNames里面。這樣,接口方法的可變字符串就被記錄了起來,后續只要獲取到參數注解內容的名字是一樣的(eg:@Path("user") String user,參數注解內容是"user“),將參數轉換(Converter,默認為StringConverter,轉換就是直接調用參數對象的toString()方法轉成字符串)放入方法路徑可成為一個真正的relativeUrl
以上就是方法注解的解析過程。

但是接口方法參數的注解還沒進行解析,那我們就繼續往下看ServiceMethod.Builder.build()方法,可以看到:

 //有多少個參數帶注解
      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        //參數類型
        Type parameterType = parameterTypes[p];
        if (Utils.hasUnresolvableType(parameterType)) {
          throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
              parameterType);
        }
        //參數對應的注解數組
        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        if (parameterAnnotations == null) {
          throw parameterError(p, "No Retrofit annotation found.");
        }
        //根據參數類型和對應注解集合進行解析,封裝到parameterHandlers中
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }

參數注解解析過程的最后調用了:parseParameter,這個方法會根據傳入的參數類型和對應注解集合進行解析,封裝成為ParameterHandler,將每個參數的注解解析最后都存入到parameterHandlers數組中,所以parameterHandlers[0]就是第一個帶注解的參數的解析內容,parameterHandlers[1]就是第二個帶注解的參數的解析內容····:

 private ParameterHandler<?> parseParameter(
        int p, Type parameterType, Annotation[] annotations) {
      ParameterHandler<?> result = null;
      for (Annotation annotation : annotations) {
        ParameterHandler<?> annotationAction = parseParameterAnnotation(
            p, parameterType, annotations, annotation);

        if (annotationAction == null) {
          continue;
        }

        if (result != null) {
          throw parameterError(p, "Multiple Retrofit annotations found, only one allowed.");
        }

        result = annotationAction;
      }

      if (result == null) {
        throw parameterError(p, "No Retrofit annotation found.");
      }

      return result;
    }

可以看到parseParameter主要做的就是遍歷參數的所有注解,一個一個進行注解解析:parseParameterAnnotation,這個方法內部代碼特別長,因為有很多種注解需要分析,在這里,我們就只抽取出@Path的注解解析部分內容:

 //參數注解解析
    private ParameterHandler<?> parseParameterAnnotation(
        int p, Type type, Annotation[] annotations, Annotation annotation) {
        ····
        ····
        ····
else if (annotation instanceof Path) {
        if (gotQuery) {
          throw parameterError(p, "A @Path parameter must not come after a @Query.");
        }
        if (gotUrl) {
          throw parameterError(p, "@Path parameters may not be used with @Url.");
        }
        if (relativeUrl == null) {
          throw parameterError(p, "@Path can only be used with relative url on @%s", httpMethod);
        }
        gotPath = true;

        Path path = (Path) annotation;
        String name = path.value();
        /**
         * 有效性檢驗:
         * 1.命名規范:必須符合正則:[a-zA-Z][a-zA-Z0-9_-]*
         * 2.注解value必須存在relativeUrlParamNames方法變量,對應起來
         */
        validatePathName(p, name);

        Converter<?, String> converter = retrofit.stringConverter(type, annotations);
        return new ParameterHandler.Path<>(name, converter, path.encoded());
      } 
        ···
        ···
        ···
}

這里對@Path的解析最主要的就是獲取一個Converter<?, String>,獲取是通過retrofit.stringConverter()

 /**
     * Returns a {@link Converter} for {@code type} to {@link String} from the available
     * {@linkplain #converterFactories() factories}.
     */
    public <T> Converter<T, String> stringConverter(Type type, Annotation[] annotations) {
        checkNotNull(type, "type == null");
        checkNotNull(annotations, "annotations == null");

        for (int i = 0, count = converterFactories.size(); i < count; i++) {
            Converter<?, String> converter =
                    converterFactories.get(i).stringConverter(type, annotations, this);
            if (converter != null) {
                //noinspection unchecked
                return (Converter<T, String>) converter;
            }
        }

        // Nothing matched. Resort to default converter which just calls toString().
        //noinspection unchecked
        return (Converter<T, String>) BuiltInConverters.ToStringConverter.INSTANCE;
    }

同樣,這里是通過遍歷converterFactories,找到一個能處理這種類型typeConverter.Factory,返回一個 Converter<?, String>,如果找不到,就使用BuiltInConverters.ToStringConverter.INSTANCE。查看下BuiltInConverters.ToStringConverter.INSTANCE源碼:

//BuiltInConverters.java
static final class ToStringConverter implements Converter<Object, String> {
    static final ToStringConverter INSTANCE = new ToStringConverter();

    @Override public String convert(Object value) {
      return value.toString();
    }
  }

可以看到,默認的StringConverter就是通過調用paramter對象的toString方法,直接將結果類型轉成String類型。
到這里,我們就明白了:

public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}

接口方法參數user的類型其實可以不用是String類型,就算是其他類型也可以,但是默認的StringConverter調用該類型對象的toString方法返回的結果要符合你自己需求。
比如,我們現在自定義一個java bean:

public class StringWrapper {
    private String content;
    public StringWrapper(String content)
    {
        this.content = content;
    }

    @Override
    public String toString() {
        return content;
    }
}
public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") StringWrapper user);
}

這樣也是可以的,因為StringWrapper.toString跟我們上面直接定義成的String最終結果是一樣的。
回到正題,parseParameterAnnotation中對@Path的解析最終會返回一個ParameterHandler.Path對象:

static final class Path<T> extends ParameterHandler<T> {
    private final String name;
    private final Converter<T, String> valueConverter;
    private final boolean encoded;

    Path(String name, Converter<T, String> valueConverter, boolean encoded) {
      this.name = checkNotNull(name, "name == null");
      this.valueConverter = valueConverter;
      this.encoded = encoded;
    }

    @Override void apply(RequestBuilder builder, @Nullable T value) throws IOException {
      if (value == null) {
        throw new IllegalArgumentException(
            "Path parameter \"" + name + "\" value must not be null.");
      }
      builder.addPathParam(name, valueConverter.convert(value), encoded);
    }
  }

最后,參數解析所有的信息都放入到了全局數據parameterHandlers中,沒個parameterHandlers[i]都包含了各個參數的所有注解解析信息。

ParameterHandler<T>

到這里,ServiceMethod.Builder.build()方法也算是解析完畢了。
總結一下:ServiceMethod的創建過程主要做了幾件事:

  1. 根據接口方法返回類型,通過遍歷retrofitadapterFactories列表,找到適合的CallAdapter<T, R> callAdapter
  2. 根據HTTP返回結果類型,通過遍歷retrofitconverterFactories列表,找到適合的Converter<ResponseBody, T> responseConverter
  3. 對接口方法注解進行解析:parseMethodAnnotation(Annotation annotation)
  4. 對接口方法參數注解進行解析:parseParameter
  5. 完成以上工作后,創建ServiceMethod對象。

最后,用一張圖來表達下ServiceMethod的創建過程:

ServiceMethod.Builder.build

現在繼續分析Retrofit.createInvocationHandler的invoke剩余部分源碼:

 OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);

這里創建了一個okHttpCall

final class OkHttpCall<T> implements retrofit2.Call<T> {
        ···
        ···
 @GuardedBy("this")
  private @Nullable okhttp3.Call rawCall;
        ···
}
OkHttpCall<T>

這里可以看到OkHttpCall內部持有一個okhttp3.Call,所以其實OkHttpCall所進行的HTTP請求實際上都是交由okhttp3.Call進行的。

InvocationHandlerinvoke最后返回了:

return serviceMethod.callAdapter.adapt(okHttpCall);

經過前面的分析,假設我們對Retrofit沒有經過特殊配置,即Retrofit采用默認配置,那么:serviceMethod.callAdapter返回的就是默認的ExecutorCallAdapterFactory.get(Call.class,annotations,retrofit)

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

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

serviceMethod.callAdapter.adapt(okHttpCall)返回的就是一個new ExecutorCallbackCall<>(callbackExecutor, okHttpCall)的對象。

static final class ExecutorCallbackCall<T> implements retrofit2.Call<T> {
        final Executor callbackExecutor;
        //HTTP請求委托類
        final retrofit2.Call<T> delegate;

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

這里可以看到,ExecutorCallbackCall就是okHttpCall的代理類,而okHttpCall又持有okhttp3.Call實例。因此,進行HTTP請求的過程就明晰了:
ExecutorCallbackCall.enqueue-->okHttpCall.enqueue-->okhttp3.Call.enqueue
ExecutorCallbackCall持有的Executor callbackExecutor默認是主線程調度器,會將ExecutorCallbackCall發送HTTP請求的返回結果回調到主線程上執行。

那我們最后就來看一下發送網絡請求的具體過程。

  • 進行網絡請求(同步/異步)

網絡請求是通過我們得到的ExecutorCallbackCall<>(callbackExecutor, okHttpCall)對象進行請求,這里就只看下異步請求過程:

repos.enqueue(new Callback<ResponseBody>() {/***/});

上面分析知道,ExecutorCallbackCall內部封裝了網絡請求和線程調度作用,而實際起網絡請求作用的是OkHttpCall
那我們就來看下OkHttpCall的異步網絡請求enqueue源碼:

@Override 
 public void enqueue(final Callback<T> callback) {
        ···
        ···
        okhttp3.Call call;
        ···
        ···

        call = rawCall = createRawCall();
        ···
        ···

        call.enqueue(new okhttp3.Callback() {
                @Override
                public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
                throws IOException {
                        Response<T> response;
                        ···
                        ···
                        callSuccess(response);
                }

                @Override
                public void onFailure(okhttp3.Call call, IOException e) {
                        ···
                        callback.onFailure(OkHttpCall.this, e);
                        ···
                }
                        ···
                        ···
        }
}

可以看到,OkHttpCall里面是通過函數createRawCall獲得一個真正的能用于HTTP網絡請求的okhttp3.Call對象,那么我們就來看下createRawCall()源碼是怎樣構建出一個okhttp3.Call對象:

 private okhttp3.Call createRawCall() throws IOException {
    Request request = serviceMethod.toRequest(args);
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }

這里,我們先來看下:

okhttp3.Call call = serviceMethod.callFactory.newCall(request);

serviceMethod.callFactory默認就是retrofitcallFactory,也就是OkHttpClient,所以這里就是由OkHttpClient創建出一個真正用于進行HTTP網絡請求的okhttp3.Call對象。

接下來我們回顧上一行代碼,可以看到是通過serviceMethod.toRequest(args)構建出一個Request,此處的args就是我們接口方法的參數,那么我們就先來看下serviceMethod.toRequest源碼是怎樣構建一個Request的:

 /** Builds an HTTP request from method arguments. */
  Request toRequest(@Nullable Object... args) throws IOException {
//從接口方法注解解析信息
    RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
        contentType, hasBody, isFormEncoded, isMultipart);

    @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
//接口方法參數注解解析信息
    ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;

    int argumentCount = args != null ? args.length : 0;
    if (argumentCount != handlers.length) {
      throw new IllegalArgumentException("Argument count (" + argumentCount
          + ") doesn't match expected count (" + handlers.length + ")");
    }

    for (int p = 0; p < argumentCount; p++) {
      handlers[p].apply(requestBuilder, args[p]);
    }

    return requestBuilder.build();
  }

所以我們前面為什么說ServiceMethodRetrofit里面是很重要的,在這里也可以知道,ServiceMethod既負責解析接口方法,接口參數,又負責從retrofit那邊獲取合適的CallAdapter和Converter,又要負責將接口解析出來的內容組裝成一個HTTP Request···可以說,ServiceMethod就是Retrofit的核心引擎。
回到toRequest函數,從上面的源碼中可以看到,首先是根據接口方法解析的信息組裝成了一個RequestBuilder,然后再根據方法參數信息(Object... args),經由之前解析的參數注解信息可以得到一個最終的RequestBuilder,由這些信息就可以build出一個Request
toRequest里面有句代碼是:

handlers[p].apply(requestBuilder, args[p]);

這里其實獲取得到的就是接口方法第p個參數解析出來的效果,舉個例子來說,比如,我們之前handlers[p]解析出來的是@Path的信息,那么handlers[p]就是一個ParameterHandler.Path類型的對象,而ParameterHandler.PathParameterHandler靜態內部類,同時也是一個ParameterHandler子類:

 static final class Path<T> extends ParameterHandler<T> {
    private final String name;
    private final Converter<T, String> valueConverter;
    private final boolean encoded;

    Path(String name, Converter<T, String> valueConverter, boolean encoded) {
      this.name = checkNotNull(name, "name == null");
      this.valueConverter = valueConverter;
      this.encoded = encoded;
    }

    @Override void apply(RequestBuilder builder, @Nullable T value) throws IOException {
      if (value == null) {
        throw new IllegalArgumentException(
            "Path parameter \"" + name + "\" value must not be null.");
      }
      builder.addPathParam(name, valueConverter.convert(value), encoded);
    }
  }

所以,handlers[p].apply(requestBuilder, args[p])按官網的例子就變成了:
Path.apply(requestBuilder,String user)-->builder.addPathParam(”user", valueConverter.convert("user"), encoded);
而由我們前面的分析,此處的valueConverter默認是ToStringConverter

 static final class ToStringConverter implements Converter<Object, String> {
    static final ToStringConverter INSTANCE = new ToStringConverter();

    @Override public String convert(Object value) {
      return value.toString();
    }
  }

所以valueConverter.convert("user")-->"user".toString()=="user",所以最終返回的就是字符串"user",所以:
builder.addPathParam(”user", valueConverter.convert("user"), encoded)-->builder.addPathParam(”user", "user", encoded)。
對于@Path來說,肯定是將參數信息替換掉接口方法注解內容相對路徑的{*}內容,所以,builder.addPathParam就是實現這個功能的:

void addPathParam(String name, String value, boolean encoded) {
    if (relativeUrl == null) {
      // The relative URL is cleared when the first query parameter is set.
      throw new AssertionError();
    }
    relativeUrl = relativeUrl.replace("{" + name + "}", canonicalizeForPath(value, encoded));
  }

經過以上步驟,就構建出了一個HTTP請求。
最后,我們就可以用這個請求進行真正的網絡發送call.enqueue,回顧上面OkHttpCall.enqueue方法,可以看到請求返回結果解析是在:

//OkHttpCall.enqueue片段代碼
  call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response<T> response;
        try {
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
        callSuccess(response);
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

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

      private void callSuccess(Response<T> response) {
        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

可以看到,請求成功的時候,會調用parseResponse得到一個我們需要的Response<T>類型對象,具體解析方法如下:

  Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();
    ···
    ···
    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    ···
      T body = serviceMethod.toResponse(catchingBody);
      return Response.success(body, rawResponse);
    ···
  }

parseResponse就是對得到的rawResponse進行處理判斷,最后交由到serviceMethod.toResponse做出最終的轉換。

 /** Builds a method return value from an HTTP response body. */
  R toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
  }

可以看到這里就是用到了數據轉換器Converter<ResponseBody, R>將HTTP返回結果ResponseBody轉換成我們自己定義的類型R(默認的Converter.FactoryBuiltInConverters,它所生產的Convert默認不對ResponseBody進行轉換)。

所以分析到了這里,Retrofit整體的流程我們也差不多整理完畢了。

最后進行總結一下:

  • 我們要是用Retrofit進行HTTP網絡請求的時候,首先要創建一個接口進行HTTP動作描述,之所以用接口是為了后面動態創建一個對應的接口代理類(java的動態代理只能支持接口);
  • 接口描述創建完成后,通過建造者模式可以配置出一個retrofit實例
  • retrofit的`create函數就可以創建出一個接口的動態代理類
  • 調用動態代理類的接口方法時,就會被動態代理類攔截,攔截的主要原因就是為了隱式的創建出一個用于HTTP網絡請求的Call對象,具體做了3件事:
    ?1. 解析接口注解內容并保存,功能類為ServiceMethod
    ?2. 創建一個OkHttpCall對象,OkHttpCall內部持有okhttp3.Call實例。OkHttpCall的作用就是從ServiceMethod和當前參數獲取得到一個Request,并通過OkHttpClient根據這個Request創建出一個okhttp3.Call對象。
    ?3. 最后從ServiceMethod中拿到一個可以處理接口方法返回類型的CallAdapter,由其adapt返回得到一個可以對HTTP請求結果進行線程調度的retrofit2.Call對象(該Call對象是OkHttpCall的代理類)。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,224評論 6 529
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 97,916評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,014評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,466評論 1 308
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,245評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,795評論 1 320
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,869評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,010評論 0 285
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,524評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,487評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,634評論 1 366
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,173評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,884評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,282評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,541評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,236評論 3 388
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,623評論 2 370

推薦閱讀更多精彩內容