Retrofit 2.0源碼解析

簡(jiǎn)介

剛接觸Retrofit的時(shí)候,就寫了一篇簡(jiǎn)單的使用介紹:Retrofit 2.0基本使用方法,算是對(duì)Retrofit的基礎(chǔ)入門。也算是接觸Retrofit一段時(shí)間了,現(xiàn)在差不多可以對(duì)源碼層進(jìn)行解析,最起碼,理解原理后可以使得我們使用起來更加得心應(yīng)手 _。

網(wǎng)絡(luò)請(qǐng)求使用基本方法

參考官網(wǎng):

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

從上一節(jié)的使用Retrofit進(jìn)行網(wǎng)絡(luò)請(qǐng)求中,我們可以看到,請(qǐng)求過程主要分為以下幾步:

  1. 創(chuàng)建一個(gè)接口進(jìn)行HTTP請(qǐng)求描述;
  2. 使用Retrofit.Builder構(gòu)建模式構(gòu)造出一個(gè)Retrofit實(shí)例;
  3. 調(diào)用retrofit.create()方法獲取請(qǐng)求接口實(shí)例;
  4. 由請(qǐng)求接口實(shí)例獲取到Call對(duì)象;
  5. 進(jìn)行網(wǎng)絡(luò)請(qǐng)求(同步/異步)

接下來,我們就按照以上正常的網(wǎng)絡(luò)請(qǐng)求順序來對(duì)Retrofit源碼進(jìn)行解析。

  • 創(chuàng)建一個(gè)接口進(jìn)行HTTP請(qǐng)求描述
public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}

這里主要做的就是采用注解的方式進(jìn)行HTTP描述,后面在第4步由請(qǐng)求接口實(shí)例獲取到Call對(duì)象時(shí)進(jìn)行反射提取注解內(nèi)容進(jìn)行HTTP請(qǐng)求構(gòu)造(如果開啟了預(yù)先加載解析(validateEagerly=true),那么在第3步調(diào)用retrofit.create()方法獲取請(qǐng)求接口實(shí)例的時(shí)候就會(huì)進(jìn)行注解解析),具體解析方法參考后續(xù)分析。

  • 使用Retrofit.Builder構(gòu)建模式構(gòu)造出一個(gè)Retrofit實(shí)例
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)方法,返回一個(gè)okhttp3.Call對(duì)象,以便讓我們進(jìn)行實(shí)際的HTTP請(qǐng)求
        //也就是說callFactory是我們用來生成一個(gè)客戶端HTTP請(qǐng)求工廠實(shí)例
        private @Nullable okhttp3.Call.Factory callFactory;
        private HttpUrl baseUrl;
        //converterFactories生產(chǎn)Converter<F, T>,用于將HTTP返回結(jié)果F類型轉(zhuǎn)換為T類型,或?qū)TTP請(qǐng)求類型F轉(zhuǎn)換為T。
        private final List<Converter.Factory> converterFactories = new ArrayList<>();
        //adapterFactories生產(chǎn) CallAdapter<R, T>,用于將retrofit2.Call<R>網(wǎng)絡(luò)請(qǐng)求類型轉(zhuǎn)換為T類型:T adapt(Call<R> var1);
        private final List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
        private @Nullable
        Executor callbackExecutor;
        private boolean validateEagerly;
        ···
        ···
        ···
}

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

  • Converter<F, T>:數(shù)據(jù)轉(zhuǎn)換器,用來將HTTP請(qǐng)求返回結(jié)果由F類型轉(zhuǎn)換為T類型,或者將HTTP請(qǐng)求類型F轉(zhuǎn)換為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,那么當(dāng)HTTP請(qǐng)求結(jié)果返回時(shí),就會(huì)由GsonConverterFactory產(chǎn)生的Converter,假設(shè)為Converter<ResponseBody, List<Repo>>,該Converter就會(huì)將HTTP返回結(jié)果ResponseBody轉(zhuǎn)換為 List<Repo>
而若是將對(duì)象轉(zhuǎn)換為數(shù)據(jù),那么假設(shè)類型為:Converter< List<Repo>, RequestBody>,該Converter在構(gòu)建請(qǐng)求體時(shí),會(huì)將List<Repo>轉(zhuǎn)換為RequestBody對(duì)象。

  • CallAdapter<R, T>:請(qǐng)求適配器,用于將retrofit2.Call<R>網(wǎng)絡(luò)請(qǐng)求類型轉(zhuǎn)換為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>對(duì)象轉(zhuǎn)換為Observable<T>類型,所以如果配置了RxJava2CallAdapterFactory,那么接口方法聲明應(yīng)該改為如下形式:

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

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

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

        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());
        }

當(dāng)我們調(diào)用:

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

就會(huì)走入:Builder()--> Builder(Platform platform)
然后我們看到,在Builder(Platform platform)構(gòu)造函數(shù)里面,會(huì)往converterFactories里面添加進(jìn)一個(gè)BuiltInConverters對(duì)象,所以默認(rèn)的ConverterFactory就是BuiltInConverters。前面說過ConverterFactory主要是用來將HTTP返回結(jié)果進(jìn)行類型轉(zhuǎn)換或者將HTTP請(qǐng)求體進(jìn)行類型轉(zhuǎn)換,然后我們看下BuiltInConverters是怎樣的轉(zhuǎn)換方式:

final class BuiltInConverters extends Converter.Factory {
  //返回結(jié)果轉(zhuǎn)換
  @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;
  }

  //請(qǐng)求轉(zhuǎn)換
  @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();
    }
  }
}

返回結(jié)果轉(zhuǎn)換的時(shí)候,有3種情況:

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

發(fā)現(xiàn)傳入的是ResponseBody,返回的也是ResponseBodyBufferingResponseBodyConverter里面有進(jìn)行特殊處理,主要是為了去除future I/O),所以我們可以認(rèn)為BuiltInConverters對(duì)HTTP返回結(jié)果沒有進(jìn)行轉(zhuǎn)換處理。

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

同理,我們來看下請(qǐng)求體轉(zhuǎn)換:

//請(qǐng)求轉(zhuǎn)換
  @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類型,那就不轉(zhuǎn)換,如果不是RequestBody類型,直接返回null

綜上所述:BuiltInConverters只能響應(yīng)ResponseBodyRequestBody,但是并不進(jìn)行任何轉(zhuǎn)換.對(duì)于其他類型,統(tǒng)統(tǒng)返回null。

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

 /**
         * 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默認(rèn)為OkHttpClient
                callFactory = new OkHttpClient();
            }

            Executor callbackExecutor = this.callbackExecutor;
            if (callbackExecutor == null) {
                //默認(rèn)的callbackExecutor為Platform.Android.MainThreadExecutor
                //MainThreadExecutor繼承Executor,并復(fù)寫execute(Runnable r),
                // execute內(nèi)部直接通過主線程Handler.post(r),即r.run發(fā)生在主線程
                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)構(gòu)造時(shí),已被傳入
            List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

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

build函數(shù)一進(jìn)去,就看到:

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

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

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

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

這里可以看到,如果沒有配置okhttp3.Call.Factory,那么就會(huì)使用默認(rèn)的HTTP工廠類:OkHttpClient,用于客戶端程序創(chuàng)建okhttp3.Call對(duì)象,以進(jìn)行實(shí)際的HTTP網(wǎng)絡(luò)請(qǐng)求。
如果沒有線程調(diào)度器callbackExecutor,那么就會(huì)使用默認(rèn)的線程調(diào)度器: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);
            }
        }
    }

從源碼可以看出,默認(rèn)的線程調(diào)度器是主線程調(diào)度器。
接下來再看:

 // 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增加了一個(gè)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請(qǐng)求委托類
        final retrofit2.Call<T> delegate;

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

在Android平臺(tái)上,callbackExecutor默認(rèn)不為null,所以defaultCallAdapterFactory返回的是ExecutorCallAdapterFactory。從ExecutorCallAdapterFactoryget函數(shù),可以看到,ExecutorCallAdapterFactory只會(huì)響應(yīng)返回類型為Call的函數(shù)聲明(所以,如果我們沒有配置addCallAdapterFactory(),那么我們接口函數(shù)聲明的返回類型必須為Call<?>),響應(yīng)處理的最終結(jié)果就是返回一個(gè)CallAdapter,這個(gè)CallAdapteradapt()函數(shù)會(huì)傳入一個(gè)HTTP請(qǐng)求委托類,然后返回一個(gè)HTTP請(qǐng)求代理類:ExecutorCallbackCall<T> implements retrofit2.Call<T>,這個(gè)代理類代理了委托類的異步HTTP網(wǎng)絡(luò)請(qǐng)求,并將返回結(jié)果通過線程調(diào)度器將回調(diào)監(jiān)聽函數(shù)分發(fā)到具體線程上執(zhí)行(默認(rèn)線程調(diào)度器是主線程調(diào)度)。

講到這里,Retrofit實(shí)例的配置創(chuàng)建就算是完成了。下面這個(gè)圖展示了Retrofit.Builder提供的配置選項(xiàng):

Builder

  • 調(diào)用retrofit.create()方法獲取請(qǐng)求接口實(shí)例
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);
        //預(yù)先加載解析注解:loadServiceMethod
        //默認(rèn)false,即調(diào)用接口方法后,才進(jìn)行解析
        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平臺(tái)使用
                        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方法返回的是一個(gè) (T) Proxy.newProxyInstance()方法產(chǎn)生的一個(gè)動(dòng)態(tài)代理對(duì)象(如果不清楚動(dòng)態(tài)代理,可以看下我之前寫的文章:Java代理模式,里面對(duì)java的動(dòng)態(tài)代理有詳細(xì)講解)。使用該動(dòng)態(tài)代理對(duì)象進(jìn)行方法調(diào)用后,會(huì)自動(dòng)被InvocationHandler攔截,最終進(jìn)入InvocationHandlerinvoke函數(shù)里面。

  • 由請(qǐng)求接口實(shí)例獲取到Call對(duì)象
Call<List<Repo>> repos = service.listRepos("octocat")

從上面create的分析中,我們知道,此處的service是一個(gè)動(dòng)態(tài)代理類對(duì)象,所以,在調(diào)用方法時(shí),會(huì)被InvocationHandlerinvoke方法攔截,所以調(diào)用:service.listRepos("octocat")就會(huì)進(jìn)入InvocationHandler.invoke()中,查看下invoke函數(shù),最主要的操作就是如下3句話:

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

ServiceMethodRetrofit中是一個(gè)很重要的類,主要做的就是對(duì)接口方法注解進(jìn)行解析,最終生成一個(gè)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是一個(gè)緩存容器,是對(duì)接口方法的解析緩存。

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

loadServiceMethod()中可以看到,ServiceMethod的實(shí)例也是通過builder模式進(jìn)行構(gòu)建的,構(gòu)建過程需傳入Retrofit對(duì)象和Method對(duì)象。

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

public ServiceMethod build() {
      //CallAdapter<T, R> callAdapter;適配Call的響應(yīng)類型,將默認(rèn)響應(yīng)類型R轉(zhuǎn)換為類型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交互中,轉(zhuǎn)換對(duì)象為數(shù)據(jù) 或 從數(shù)據(jù)轉(zhuǎn)換為對(duì)象
      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();

首先創(chuàng)建一個(gè)callAdapter,具體創(chuàng)建過程如下:

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

可以看到,其最終調(diào)用到的是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數(shù)組中,遍歷找到一個(gè)可以處理該接口方法返回類型和注解的CallAdapter<?, ?>。那根據(jù)我們之前的分析,如果我們沒有進(jìn)行CallAdapter的配置,那么默認(rèn)的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);
                }
            };
        }
    }

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

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

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

 //Converter<ResponseBody, T> responseConverter;HTTP交互中,轉(zhuǎn)換對(duì)象為數(shù)據(jù) 或 從數(shù)據(jù)轉(zhuǎn)換為對(duì)象
      responseConverter = createResponseConverter();

responseConverterConverter<ResponseBody, T>類型,其實(shí)我們一看到這個(gè),就應(yīng)該大概知道是怎么做了,肯定又是跟retrofit請(qǐng)求,retrofit又從倉(cāng)庫(kù)中進(jìn)行查找,只是這回是從List<Converter.Factory> converterFactories中查找,直到找到一個(gè)能處理這種responseTypeConverter.Factory,由其返回一個(gè)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
        ···
        ···
        ···
    }

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

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

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

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

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

這個(gè)是一個(gè)很重要的操作,就是對(duì)接口方法進(jìn)行解析,追蹤進(jìn)去再看下解析源碼:

 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;
      }
    }

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

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

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

按照官網(wǎng)那個(gè)例子,那么:this.relativeUrl = value = "users/{user}/repos",在parseHttpMethodAndPath最后,調(diào)用了 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;
  }

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

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

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

參數(shù)注解解析過程的最后調(diào)用了:parseParameter,這個(gè)方法會(huì)根據(jù)傳入的參數(shù)類型和對(duì)應(yīng)注解集合進(jìn)行解析,封裝成為ParameterHandler,將每個(gè)參數(shù)的注解解析最后都存入到parameterHandlers數(shù)組中,所以parameterHandlers[0]就是第一個(gè)帶注解的參數(shù)的解析內(nèi)容,parameterHandlers[1]就是第二個(gè)帶注解的參數(shù)的解析內(nèi)容····:

 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主要做的就是遍歷參數(shù)的所有注解,一個(gè)一個(gè)進(jìn)行注解解析:parseParameterAnnotation,這個(gè)方法內(nèi)部代碼特別長(zhǎng),因?yàn)橛泻芏喾N注解需要分析,在這里,我們就只抽取出@Path的注解解析部分內(nèi)容:

 //參數(shù)注解解析
    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();
        /**
         * 有效性檢驗(yàn):
         * 1.命名規(guī)范:必須符合正則:[a-zA-Z][a-zA-Z0-9_-]*
         * 2.注解value必須存在relativeUrlParamNames方法變量,對(duì)應(yīng)起來
         */
        validatePathName(p, name);

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

這里對(duì)@Path的解析最主要的就是獲取一個(gè)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,找到一個(gè)能處理這種類型typeConverter.Factory,返回一個(gè) 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();
    }
  }

可以看到,默認(rèn)的StringConverter就是通過調(diào)用paramter對(duì)象的toString方法,直接將結(jié)果類型轉(zhuǎn)成String類型。
到這里,我們就明白了:

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

接口方法參數(shù)user的類型其實(shí)可以不用是String類型,就算是其他類型也可以,但是默認(rèn)的StringConverter調(diào)用該類型對(duì)象的toString方法返回的結(jié)果要符合你自己需求。
比如,我們現(xiàn)在自定義一個(gè)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);
}

這樣也是可以的,因?yàn)?code>StringWrapper.toString跟我們上面直接定義成的String最終結(jié)果是一樣的。
回到正題,parseParameterAnnotation中對(duì)@Path的解析最終會(huì)返回一個(gè)ParameterHandler.Path對(duì)象:

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);
    }
  }

最后,參數(shù)解析所有的信息都放入到了全局?jǐn)?shù)據(jù)parameterHandlers中,沒個(gè)parameterHandlers[i]都包含了各個(gè)參數(shù)的所有注解解析信息。

ParameterHandler<T>

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

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

最后,用一張圖來表達(dá)下ServiceMethod的創(chuàng)建過程:

ServiceMethod.Builder.build

現(xiàn)在繼續(xù)分析Retrofit.createInvocationHandler的invoke剩余部分源碼:

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

這里創(chuàng)建了一個(gè)okHttpCall

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

這里可以看到OkHttpCall內(nèi)部持有一個(gè)okhttp3.Call,所以其實(shí)OkHttpCall所進(jìn)行的HTTP請(qǐng)求實(shí)際上都是交由okhttp3.Call進(jìn)行的。

InvocationHandlerinvoke最后返回了:

return serviceMethod.callAdapter.adapt(okHttpCall);

經(jīng)過前面的分析,假設(shè)我們對(duì)Retrofit沒有經(jīng)過特殊配置,即Retrofit采用默認(rèn)配置,那么:serviceMethod.callAdapter返回的就是默認(rèn)的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)返回的就是一個(gè)new ExecutorCallbackCall<>(callbackExecutor, okHttpCall)的對(duì)象。

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

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

這里可以看到,ExecutorCallbackCall就是okHttpCall的代理類,而okHttpCall又持有okhttp3.Call實(shí)例。因此,進(jìn)行HTTP請(qǐng)求的過程就明晰了:
ExecutorCallbackCall.enqueue-->okHttpCall.enqueue-->okhttp3.Call.enqueue
ExecutorCallbackCall持有的Executor callbackExecutor默認(rèn)是主線程調(diào)度器,會(huì)將ExecutorCallbackCall發(fā)送HTTP請(qǐng)求的返回結(jié)果回調(diào)到主線程上執(zhí)行。

那我們最后就來看一下發(fā)送網(wǎng)絡(luò)請(qǐng)求的具體過程。

  • 進(jìn)行網(wǎng)絡(luò)請(qǐng)求(同步/異步)

網(wǎng)絡(luò)請(qǐng)求是通過我們得到的ExecutorCallbackCall<>(callbackExecutor, okHttpCall)對(duì)象進(jìn)行請(qǐng)求,這里就只看下異步請(qǐng)求過程:

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

上面分析知道,ExecutorCallbackCall內(nèi)部封裝了網(wǎng)絡(luò)請(qǐng)求和線程調(diào)度作用,而實(shí)際起網(wǎng)絡(luò)請(qǐng)求作用的是OkHttpCall
那我們就來看下OkHttpCall的異步網(wǎng)絡(luò)請(qǐng)求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里面是通過函數(shù)createRawCall獲得一個(gè)真正的能用于HTTP網(wǎng)絡(luò)請(qǐng)求的okhttp3.Call對(duì)象,那么我們就來看下createRawCall()源碼是怎樣構(gòu)建出一個(gè)okhttp3.Call對(duì)象:

 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默認(rèn)就是retrofitcallFactory,也就是OkHttpClient,所以這里就是由OkHttpClient創(chuàng)建出一個(gè)真正用于進(jìn)行HTTP網(wǎng)絡(luò)請(qǐng)求的okhttp3.Call對(duì)象。

接下來我們回顧上一行代碼,可以看到是通過serviceMethod.toRequest(args)構(gòu)建出一個(gè)Request,此處的args就是我們接口方法的參數(shù),那么我們就先來看下serviceMethod.toRequest源碼是怎樣構(gòu)建一個(gè)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.
//接口方法參數(shù)注解解析信息
    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既負(fù)責(zé)解析接口方法,接口參數(shù),又負(fù)責(zé)從retrofit那邊獲取合適的CallAdapter和Converter,又要負(fù)責(zé)將接口解析出來的內(nèi)容組裝成一個(gè)HTTP Request···可以說,ServiceMethod就是Retrofit的核心引擎。
回到toRequest函數(shù),從上面的源碼中可以看到,首先是根據(jù)接口方法解析的信息組裝成了一個(gè)RequestBuilder,然后再根據(jù)方法參數(shù)信息(Object... args),經(jīng)由之前解析的參數(shù)注解信息可以得到一個(gè)最終的RequestBuilder,由這些信息就可以build出一個(gè)Request。
toRequest里面有句代碼是:

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

這里其實(shí)獲取得到的就是接口方法第p個(gè)參數(shù)解析出來的效果,舉個(gè)例子來說,比如,我們之前handlers[p]解析出來的是@Path的信息,那么handlers[p]就是一個(gè)ParameterHandler.Path類型的對(duì)象,而ParameterHandler.PathParameterHandler靜態(tài)內(nèi)部類,同時(shí)也是一個(gè)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])按官網(wǎng)的例子就變成了:
Path.apply(requestBuilder,String user)-->builder.addPathParam(”user", valueConverter.convert("user"), encoded);
而由我們前面的分析,此處的valueConverter默認(rèn)是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)。
對(duì)于@Path來說,肯定是將參數(shù)信息替換掉接口方法注解內(nèi)容相對(duì)路徑的{*}內(nèi)容,所以,builder.addPathParam就是實(shí)現(xiàn)這個(gè)功能的:

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));
  }

經(jīng)過以上步驟,就構(gòu)建出了一個(gè)HTTP請(qǐng)求。
最后,我們就可以用這個(gè)請(qǐng)求進(jìn)行真正的網(wǎng)絡(luò)發(fā)送call.enqueue,回顧上面OkHttpCall.enqueue方法,可以看到請(qǐng)求返回結(jié)果解析是在:

//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();
        }
      }

可以看到,請(qǐng)求成功的時(shí)候,會(huì)調(diào)用parseResponse得到一個(gè)我們需要的Response<T>類型對(duì)象,具體解析方法如下:

  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就是對(duì)得到的rawResponse進(jìn)行處理判斷,最后交由到serviceMethod.toResponse做出最終的轉(zhuǎn)換。

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

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

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

最后進(jìn)行總結(jié)一下:

  • 我們要是用Retrofit進(jìn)行HTTP網(wǎng)絡(luò)請(qǐng)求的時(shí)候,首先要?jiǎng)?chuàng)建一個(gè)接口進(jìn)行HTTP動(dòng)作描述,之所以用接口是為了后面動(dòng)態(tài)創(chuàng)建一個(gè)對(duì)應(yīng)的接口代理類(java的動(dòng)態(tài)代理只能支持接口);
  • 接口描述創(chuàng)建完成后,通過建造者模式可以配置出一個(gè)retrofit實(shí)例
  • retrofit的`create函數(shù)就可以創(chuàng)建出一個(gè)接口的動(dòng)態(tài)代理類
  • 調(diào)用動(dòng)態(tài)代理類的接口方法時(shí),就會(huì)被動(dòng)態(tài)代理類攔截,攔截的主要原因就是為了隱式的創(chuàng)建出一個(gè)用于HTTP網(wǎng)絡(luò)請(qǐng)求的Call對(duì)象,具體做了3件事:
    ?1. 解析接口注解內(nèi)容并保存,功能類為ServiceMethod。
    ?2. 創(chuàng)建一個(gè)OkHttpCall對(duì)象,OkHttpCall內(nèi)部持有okhttp3.Call實(shí)例。OkHttpCall的作用就是從ServiceMethod和當(dāng)前參數(shù)獲取得到一個(gè)Request,并通過OkHttpClient根據(jù)這個(gè)Request創(chuàng)建出一個(gè)okhttp3.Call對(duì)象。
    ?3. 最后從ServiceMethod中拿到一個(gè)可以處理接口方法返回類型的CallAdapter,由其adapt返回得到一個(gè)可以對(duì)HTTP請(qǐng)求結(jié)果進(jìn)行線程調(diào)度的retrofit2.Call對(duì)象(該Call對(duì)象是OkHttpCall的代理類)。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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