Retrofit相關(guān)源碼解析

Retrofit這個(gè)開(kāi)源庫(kù)出來(lái)也有一定年頭了,記得之前還是在V1.0的版本的時(shí)候,之前在三月份也寫過(guò)一個(gè)Retrofit的使用簡(jiǎn)析,那會(huì)兒正是1.0向2.0過(guò)渡的時(shí)候,所以新版本老版本對(duì)比了一下!時(shí)至今日,相關(guān)文章已經(jīng)層出不窮了,今天主要是打開(kāi)它的源碼,了解一些細(xì)節(jié)的問(wèn)題!

準(zhǔn)備工作

基于版本:

compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0'

相關(guān)問(wèn)題:

1、Retrofit是使用注解確定對(duì)應(yīng)的請(qǐng)求方式和參數(shù)的,那么具體的url是怎么產(chǎn)生出來(lái)的的呢?

2、我們定義的是一個(gè)接口,那么Retrofit又是怎么生成對(duì)應(yīng)的實(shí)現(xiàn)類的呢?

3、網(wǎng)絡(luò)請(qǐng)求V2.0開(kāi)始統(tǒng)一使用OkHttp了,那么異步回調(diào)到主線程是如何實(shí)現(xiàn)的?

4、同一個(gè)方法,支持Call<T> 的返回類型,又可以支持Observable<T>的返回類型,這個(gè)又是如何實(shí)現(xiàn)的?

5、同一個(gè)方法,支持不同的轉(zhuǎn)換(GsonJacksonMoshiFastJson等等),這個(gè)又是如何實(shí)現(xiàn)的呢?

帶著這些問(wèn)題,我們可以更好的進(jìn)行相關(guān)的源碼分析

第一部分 Retrofit && ServiceMethod的創(chuàng)建

從Retrofit的構(gòu)建方法開(kāi)始說(shuō)起

new Retrofit.Builder()
        .baseUrl("http://10.0.60.115:60321/1.0/")
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .client(new OkHttpClient.Builder()
                .addInterceptor(new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        return chain.proceed(RequestUtils.createLoginJsonRequest(chain.request()));
                    }
                })
                .addNetworkInterceptor(
                        new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.HEADERS))
                .build())
        .build()
        .create(LoginApi.class);

這里就是顯而易見(jiàn)的builder模,通過(guò)Builder去構(gòu)建我們需要的一些必要數(shù)據(jù)(比如說(shuō)baseUrl,callAdapter,Conver等等),接下來(lái)看看Builder里面具體做了些什么!!

調(diào)用Retrofit內(nèi)部的Builder的空參數(shù)構(gòu)造方法!:

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

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

在這里,又去調(diào)用了Platform.get()初始化了一個(gè)Platform,并把默認(rèn)的轉(zhuǎn)換器BuiltInConverters初始化并加入了集合中!!

那么問(wèn)題來(lái)了,這個(gè)Platform是何方神圣,具體有撒作用??順藤摸瓜,這里開(kāi)始介紹內(nèi)部的第一個(gè)神秘嘉賓!!

Platform 初始化

private static final Platform PLATFORM = findPlatform();//初始化`Platform`的靜態(tài)方法

Platform字面意思就是平臺(tái)啦,所以Platform相當(dāng)于一個(gè)抽象類,這個(gè)類里面有對(duì)應(yīng)的實(shí)現(xiàn)類:Android iOS Java 8對(duì)應(yīng)的是各種具體平臺(tái)。

  private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("java.util.Optional");
      return new Java8();
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("org.robovm.apple.foundation.NSObject");
      return new IOS();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }

可以看到,在調(diào)用findPlatform()方法之后就回去判斷初始化對(duì)應(yīng)的具體平臺(tái),具體的實(shí)現(xiàn)類就是上面說(shuō)到的三個(gè),Android Java iOS,你沒(méi)有看錯(cuò),還有iOS的(這里是用的Swift),嘖嘖。。

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

    @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
      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);
      }
    }
  }

各個(gè)不同的平臺(tái)其實(shí)就是根據(jù)不同的環(huán)境初始化不同的MainThreadExecutor,像上面的Android平臺(tái)當(dāng)然就是獲取主線程的Handler!!這里可以看到,在初始化Platform之后,通過(guò)Platform得到的ExecutorCallAdapterFactory的工廠的Executor其實(shí)就是運(yùn)行在主線程的Executor

Builder的默認(rèn)構(gòu)造函數(shù)基本上講完了!其實(shí)就是通過(guò)對(duì)應(yīng)的平臺(tái)構(gòu)建了一個(gè)具體的Platform,通過(guò)這個(gè)Platform構(gòu)建出了對(duì)應(yīng)平臺(tái)的主線程隊(duì)列的線程池,方便后面的方法回調(diào)到主線程中!這里基本上也可以回答第三個(gè)問(wèn)題了,異步怎么回調(diào)到主線程的!

添加baseUrl

public Builder baseUrl(HttpUrl baseUrl) {
  checkNotNull(baseUrl, "baseUrl == null");
  List<String> pathSegments = baseUrl.pathSegments();
  if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
    throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
  }
  this.baseUrl = baseUrl;
  return this;
}

這里沒(méi)撒說(shuō)的,就是檢測(cè)一下url的格式,然后完成賦值!

addConverterFactory && addCallAdapterFactory

/** Add converter factory for serialization and deserialization of objects. */
public Builder addConverterFactory(Converter.Factory factory) {
  converterFactories.add(checkNotNull(factory, "factory == null"));
  return this;
}

/**
 * Add a call adapter factory for supporting service method return types other than {@link
 * Call}.
 */
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
  adapterFactories.add(checkNotNull(factory, "factory == null"));
  return this;
}

這里忍不住必須說(shuō)兩句了,這兩個(gè)方法套路是完全一樣——適配器模式,CallAdapter是請(qǐng)求Call對(duì)應(yīng)的適配器,CallAdapter.Factory是創(chuàng)建對(duì)應(yīng)CallAdapter的抽象工廠!! Converter是解析的轉(zhuǎn)換器,這里提供了三種轉(zhuǎn)換場(chǎng)景,responseBodyConverterrequestBodyConverterstringConverterConverter.Factory則是Convert的抽象工廠,這樣利于我們的后期擴(kuò)展,比如說(shuō)外國(guó)人肯定沒(méi)有寫對(duì)應(yīng)FastJsonCovert,但是它提供了工廠的嘛,我們繼承這個(gè)抽象工廠,實(shí)現(xiàn)出來(lái)就好了!!

RxJavaCallAdapterFactory

在RxJavaCallAdapterFactory這個(gè)工廠中,又定義了兩種 ,一種是SimpleCallAdapter另外一種是ResultCallAdapter,

    //SimpleCallAdapter
    @Override public <R> Observable<R> adapt(Call<R> call) {
  Observable<R> observable = Observable.create(new CallOnSubscribe<>(call)) //
      .flatMap(new Func1<Response<R>, Observable<R>>() {
        @Override public Observable<R> call(Response<R> response) {
          if (response.isSuccessful()) {
            return Observable.just(response.body());
          }
          return Observable.error(new HttpException(response));
        }
      });
  if (scheduler != null) {
    return observable.subscribeOn(scheduler);
  }
  return observable;
}

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

通俗的說(shuō)其實(shí)就是根據(jù)返回值類型判斷返回的Observable是否需要處理一下對(duì)應(yīng)的Response!!使用flatMap()將其包裝為一個(gè)新的Observable返回!!

Retrofit在創(chuàng)建的build()方法:

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

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

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

  // Make a defensive copy of the adapters and add the default Call adapter.
  List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
  //添加完之后再添加一個(gè)defaultCallAdapterFactory
  adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

  // Make a defensive copy of the converters.
  List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

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

//這個(gè)方法是上面提到的platform里面的方法,通過(guò)這個(gè)方法,將主線程的線程池和ExecutorCallAdapterFactory關(guān)聯(lián)起來(lái)了!!
  CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
    if (callbackExecutor != null) {
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }
    return DefaultCallAdapterFactory.INSTANCE;
  }

到這里,Builder的創(chuàng)建過(guò)程分析完畢,總結(jié)起來(lái)就是創(chuàng)建出具體的Platform,通過(guò)具體的Platform創(chuàng)建出主線程的線程池,然后構(gòu)建出默認(rèn)的ExecutorCallAdapterFactory,另外就是添加對(duì)應(yīng)的CallAdapter.Factory(比如說(shuō)RxJavaCallAdapterFactory 等)和Converter.Factory!


生成接口的代理對(duì)象

build()方法創(chuàng)建對(duì)應(yīng)的Retrofit之后就是create(Class<T> service)的方法,這里就是生成對(duì)應(yīng)的接口的代理類的方法!!

  @SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
  public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

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

可以看到,在調(diào)用create()方法之后,是通過(guò)Proxy生成對(duì)應(yīng)的動(dòng)態(tài)代理!這里就很好說(shuō)咯,在對(duì)應(yīng)的invoke()的方法中完成具體的請(qǐng)求!

如果Java的動(dòng)態(tài)代理不清楚或者已經(jīng)忘記了的親們,這里先簡(jiǎn)單腦補(bǔ)一下,代理的對(duì)應(yīng)方法最后都會(huì)交給InvocationHandler這個(gè)類,并通過(guò)invoke(Object proxy, Method method, Object... args)的方法去執(zhí)行相關(guān)的邏輯,這里的Method是對(duì)應(yīng)具體方法的信息摘要,反射對(duì)象,里面包含了method的名稱,參數(shù)類型,包括注解那些反正是應(yīng)有盡有啦!這個(gè)args就是具體的方法參數(shù)了!

接下來(lái)就要注意啦,在創(chuàng)建好了Retrofit之后,在生成動(dòng)態(tài)代理之后,咱們的請(qǐng)求方法還沒(méi)有構(gòu)建出來(lái)呢!所以呢,接下來(lái)肯定就是構(gòu)建相關(guān)的請(qǐng)求方法咯!!

但是明確看到,在返回動(dòng)態(tài)代理之前我們看到這里有一個(gè)判斷validateEagerly,而且對(duì)應(yīng)的Builder 對(duì)外提供了一個(gè)設(shè)置的方法!

/**
 * When calling {@link #create} on the resulting {@link Retrofit} instance, eagerly validate
 * the configuration of all methods in the supplied interface.
 */
public Builder validateEagerly(boolean validateEagerly) {
  this.validateEagerly = validateEagerly;
  return this;
}

這個(gè)方法到底是來(lái)做撒的呢?英語(yǔ)好的應(yīng)該都看明白了!我先繞個(gè)關(guān)子不講了!!

直接到代理的invoke()方法中,這里有兩個(gè)條件判斷,第一個(gè)是判斷返回的類型如果就是Object,那就撒都不搞了,直接執(zhí)行!

第二個(gè)判斷如果這個(gè)方法是Default的,這個(gè)主要是針對(duì)java8來(lái)說(shuō)得呢!所以重點(diǎn)還是要跳過(guò)到最下面!

ServiceMethod serviceMethod = loadServiceMethod(method);

ServiceMethod的創(chuàng)建

繼上面說(shuō)過(guò)的Platform之后,ServiceMethod是我們開(kāi)始講解的第二個(gè)類了!這里開(kāi)始創(chuàng)建出對(duì)應(yīng)的ServiceMethod對(duì)象,到這個(gè)方法里面具體看看!

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

舉個(gè)例子,比如說(shuō)我們?cè)贚oginApi這個(gè)接口里面定義了兩個(gè)方法:

@POST("users")//https://api.bmob.cn/1/ 注冊(cè)用戶
Call<UserBean> registerUser( @Body UserBean bean);
@GET("getUserInfo")//https://api.bmob.cn/1/用戶登陸
Observable<Result<UserBean>> login(@QueryMap Map<String,String> map);

那么當(dāng)我們執(zhí)行login()方法的時(shí)候,就會(huì)創(chuàng)建Retrofit,并且創(chuàng)建這個(gè)LoginApi的動(dòng)態(tài)代理,然后調(diào)用login()方法,那么這里loadServiceMethod(Method method)中的method方法就是login()這個(gè)方法的對(duì)象。然后通過(guò)ServiceMethod.Builder去構(gòu)建這個(gè)具體的ServiceMethod

//ServiceMethod.Builder的構(gòu)造方法
public Builder(Retrofit retrofit, Method method) {
  this.retrofit = retrofit;
  this.method = method;
  this.methodAnnotations = method.getAnnotations();//獲取方法的對(duì)應(yīng)注解@retrofit2.http.POST(value=files/{fileName})
  this.parameterTypes = method.getGenericParameterTypes();//獲取方法參數(shù)的類型
  this.parameterAnnotationsArray = method.getParameterAnnotations();//獲取方法參數(shù)的注解
}

接下來(lái)重點(diǎn)看看ServiceMethod.Builder.builder()的構(gòu)建過(guò)程!這里算是Retrofit里面比較重要的一塊了吧,因?yàn)樗_(kāi)始拼接url、確定返回類型、明確CallAdapterresponseConverte

  public ServiceMethod build() {
      //1、獲取對(duì)應(yīng)的callAdapter
      callAdapter = createCallAdapter();
      //2、獲取對(duì)應(yīng)的response的類型
      responseType = callAdapter.responseType();
      //3、創(chuàng)建response的轉(zhuǎn)換器
      responseConverter = createResponseConverter();
      for (Annotation annotation : methodAnnotations) {
        //4、根據(jù)方法的注解(GET POST)開(kāi)始具體的解析
        parseMethodAnnotation(annotation);
      }
      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
          ..........

        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
          ........
        //5、解析對(duì)應(yīng)的方法參數(shù)注解
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }

      return new ServiceMethod<>(this);
    }
  • 1、獲取對(duì)應(yīng)的callAdapter

      private CallAdapter<?> createCallAdapter() {
            //獲取返回值的Type,后面會(huì)用到
            Type returnType = method.getGenericReturnType();
            ......
            Annotation[] annotations = method.getAnnotations();
            try {
                      //調(diào)用retrofit的方法
              return retrofit.callAdapter(returnType, annotations);
            } catch (RuntimeException e) { // Wide exception range because factories are user code.
              throw methodError(e, "Unable to create call adapter for %s", returnType);
            }
          }
         //callAdapter()方法最終調(diào)用nextCallAdapter()來(lái)確定具體的callAdapter
        public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
    Annotation[] annotations) {
          ....
    
          int start = adapterFactories.indexOf(skipPast) + 1;
          for (int i = start, count = adapterFactories.size(); i < count; i++) {
                    //get是抽象方法,由具體的factory去實(shí)現(xiàn)
            CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
            if (adapter != null) {
              return adapter;
            }
          }
         .....
        }
    

前面在說(shuō)Retrofit的初始化的時(shí)候,就說(shuō)了默認(rèn)會(huì)添加ExecutorCallAdapterFactory,如果我們添加了RxJava支持了添加一個(gè)RxJavaCallAdapterFactory的話,那我們這里就有兩個(gè)CallAdapter了,那么Retrofit是如何明確到底應(yīng)該使用哪個(gè)Adapter的呢?(問(wèn)題四)相關(guān)的答案都在get()的方法中!我們可以看看這兩個(gè)Factory里面具體的get方法是怎么處理的!

      //ExecutorCallAdapterFactory中
        @Override
      public CallAdapter<Call<?>> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
        //可以處理Call的返回類型
        if (getRawType(returnType) != Call.class) {
          return null;
        }
        final Type responseType = Utils.getCallResponseType(returnType);
        return new CallAdapter<Call<?>>() {
          @Override public Type responseType() {
            return responseType;
          }

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

      //RxJavaCallAdapterFactory中
        @Override
      public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
        Class<?> rawType = getRawType(returnType);
        String canonicalName = rawType.getCanonicalName();
        boolean isSingle = "rx.Single".equals(canonicalName);
        boolean isCompletable = "rx.Completable".equals(canonicalName);
        //可以處理 Observable rx.Single rx.Completable的類型
        if (rawType != Observable.class && !isSingle && !isCompletable) {
          return null;
        }
      ....
      }

答案很是清晰明了啊,不同的adapter在get()中處理不同的邏輯!

  • 2、獲取對(duì)應(yīng)的response的類型

這里的response其實(shí)就是之前的獲取到的returnType在獲取到的里面的具體類型,比如說(shuō)returnType是Call<UserInfo>,那么這里就獲取到對(duì)應(yīng)的UserInfo,相關(guān)方法封裝放在Utils這個(gè)工具類中滴!!

  • 3、創(chuàng)建response的轉(zhuǎn)換器

      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);
        }
      }
    
    
        public <T> Converter<ResponseBody, T> nextResponseBodyConverter(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;
        }
      }
      ....
      }
    

這里其實(shí)和前面的創(chuàng)建CallAdapter的原理是一致的!最后調(diào)用RetrofitresponseBodyConverter()方法,最后調(diào)用nextResponseBodyConverter()的方法,這里這個(gè)行為模式就是傳說(shuō)中的責(zé)任鏈模式吧!如果添加了多個(gè),json解析的是要放最后面的,因?yàn)樗莵?lái)者不拒的了!!

  • 4、根據(jù)方法的注解(GET POST)開(kāi)始具體的解析
    到這里就要開(kāi)始解析方法上的對(duì)應(yīng)注解了!

比如說(shuō)下面這個(gè)Get請(qǐng)求:

@GET("news/before/{date}")
Observable<DailyStories> getBeforeDailyStories(@Path("date") String date);

在通過(guò)parseMethodAnnotation()方法之后,會(huì)繼續(xù)執(zhí)行parseHttpMethodAndPath("GET", ((GET) annotation).value(), false)的方法!

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

parseHttpMethodAndPath()中進(jìn)行httpMethod、hasBody、relativeUrl、relativeUrlParamNames的賦值!

    private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
      ...
      this.httpMethod = httpMethod;//GET
      this.hasBody = hasBody;//false
      ...
      this.relativeUrl = value;//news/before/{date}
      this.relativeUrlParamNames = parsePathParameters(value);
    }

最后一個(gè)parsePathParameters()需要我們著重看一下,到這就要進(jìn)行相關(guān){date}的替換了!

  static Set<String> parsePathParameters(String path) {
    //static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
    Matcher m = PARAM_URL_REGEX.matcher(path);
    Set<String> patterns = new LinkedHashSet<>();
    while (m.find()) {
      patterns.add(m.group(1));
    }
    return patterns;
  }

因?yàn)?code>{date}這一塊是需要替換成方法參數(shù)里面對(duì)應(yīng)的那個(gè)具體值的,這里通過(guò)relativeUrlParamNames()的方法,先將{date}取出存入了set集合中!!方便后面根據(jù)方法上對(duì)應(yīng)的參數(shù)進(jìn)行替換!!

解析對(duì)應(yīng)的方法參數(shù)

接下來(lái)就是解析方法對(duì)應(yīng)的參數(shù)的注解了:

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

這里出現(xiàn)了一個(gè)新的類ParameterHandler,這也是第三個(gè)需要介紹的類了!

ParameterHandler

ParameterHandler.png

如圖所示,ParameterHandler它是一個(gè)抽象類,有這么多具體的實(shí)現(xiàn)小弟來(lái)管理某個(gè)具體參數(shù)!里面還有一個(gè)抽象方法apply()需要每個(gè)子類去實(shí)現(xiàn)的。這個(gè)方法將在后面將具體參數(shù)封裝到RequestBuilder里面。在上面舉例的方法:

  //parameterCount=1,parameterTypes[0]=String.class
   getBeforeDailyStories(@Path("date") String date)

所以最后就是執(zhí)行parseParameter(0,String,Path),并且返回的就是ParameterHandler的對(duì)象!接下來(lái)具體看內(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;
    }

這里接著去調(diào)用parseParameterAnnotation()的方法,這也是ParameterHandler具體創(chuàng)建的方法!

    private ParameterHandler<?> parseParameterAnnotation(
    int p, Type type, Annotation[] annotations, Annotation annotation) {
      ...

      } else if (annotation instanceof Path) {
      ...
        gotPath = true;

        Path path = (Path) annotation;
        String name = path.value();
        validatePathName(p, name);

        Converter<?, String> converter = retrofit.stringConverter(type, annotations);
        //創(chuàng)建出對(duì)應(yīng)的PathParameterHandler!!
        return new ParameterHandler.Path<>(name, converter, path.encoded());

      } .......

      return null; // Not a Retrofit annotation.
    }

這里會(huì)根據(jù)不同的類型創(chuàng)建不同的Convert,比如說(shuō)解析Path就是使用StringConver,并且會(huì)先調(diào)用validatePathName()的方法去判斷之前的Set集合里面是否有這個(gè)值,如果有,那么就創(chuàng)建出一個(gè)ParameterHandler.Path的對(duì)象!
同理解析Body的時(shí)候就會(huì)去調(diào)用nextRequestBodyConverter()的方法最終確認(rèn)對(duì)應(yīng)的Convert,就這樣,最后創(chuàng)建出了ParameterHandler.Body這個(gè)具體的ParameterHandler對(duì)象!并且相關(guān)方法的參數(shù)的注解也解析出來(lái)并封裝到了parameterHandlers數(shù)組中!

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

到了這里,ServiceMethod的初始化完成,那么每次都去辛辛苦苦的構(gòu)建這些注解和參數(shù)是不是太累了?!所以必須把它緩存起來(lái)咯!這里也是上面提出的那個(gè)validateEagerlyeagerlyValidateMethods()問(wèn)題的答案:如果我們需要盡快構(gòu)建出每個(gè)方法的ServiceMethod,那么就將validateEagerly設(shè)置為true就好了!


第二部分 HTTP請(qǐng)求 響應(yīng) 轉(zhuǎn)換

經(jīng)過(guò)上面一系列的準(zhǔn)備工作,接下來(lái)就是開(kāi)始相關(guān)的網(wǎng)絡(luò)請(qǐng)求了!回到Retrofit的代理方法中:

 //上面已經(jīng)創(chuàng)建好對(duì)應(yīng)的ServiceMethod了!
ServiceMethod serviceMethod = loadServiceMethod(method);
//初始化OkHttpCall 
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
//執(zhí)行具體的call
return serviceMethod.callAdapter.adapt(okHttpCall);

OkHttpCall

沒(méi)有記錯(cuò)的話,OkHttpCall是我們要介紹的第四個(gè)對(duì)象了!也是比較重要的一個(gè)對(duì)象了,OkHttpCall 實(shí)現(xiàn)了 Call接口,內(nèi)部持有okhttp3.Call的引用,所以可以理解為它是OkHttpCall的代理對(duì)象!

OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);

這里構(gòu)建出一個(gè)具體的OkHttpCall的對(duì)象!然后調(diào)用了serviceMethod.callAdapter.adapt(okHttpCall)這個(gè)方法,接下來(lái)著重分析這個(gè)方法做了些什么操作!
adapt()CallAdapter里面的抽象方法,由具體的子類實(shí)現(xiàn)!如果我們返回的是Call類型的,那么由上面第一部分分析,ServiceMethod這里就是是用的ExecutorCallAdapterFactory!那么到ExecutorCallAdapterFactory中看看具體的實(shí)現(xiàn)邏輯!!

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

這里又返回了一個(gè)ExecutorCallbackCall的對(duì)象!這里的callbackExecutor就是在講初始化Platform創(chuàng)建的!
當(dāng)我們調(diào)用具體的方法時(shí):

login.enqueue(new Callback<UserBean>() {
        @Override
        public void onResponse(Call<UserBean> call, Response<UserBean> response) {
            
        }

        @Override
        public void onFailure(Call<UserBean> call, Throwable t) {     

        }
    });

其實(shí)就是調(diào)用ExecutorCallbackCall里面的對(duì)應(yīng)方法咯!

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

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

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

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

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

通過(guò)上面的方法就可以完全明白為什么enqueue的方法都是在主線程上的了!!

這里的delegate就是之前傳入的OkHttpCall對(duì)象,所以這里又會(huì)去執(zhí)行OkHttpCall里面的enqueue()方法,繞了半天,終于又回到了OkHttpCall里面了!

  @Override 
public void enqueue(final Callback<T> callback) {
    ....
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      call = rawCall;
      failure = creationFailure;
      if (call == null && failure == null) {
        try {
          //如果call沒(méi)有創(chuàng)建那么就去創(chuàng)建!
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          failure = creationFailure = t;
        }
      }
    }

    ....

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

這個(gè)方法有點(diǎn)兒長(zhǎng),主要是判斷有木有創(chuàng)建okhttp3.Call,沒(méi)有就去創(chuàng)建,創(chuàng)建了就調(diào)用call的call.enqueue()方法,最后再將結(jié)果通過(guò)傳入的Callback回調(diào)出去!

RequestBuilder

先說(shuō)okhttp3.Call的創(chuàng)建:

call = rawCall = createRawCall();

這里調(diào)用了OkHttpCall里面的createRawCall()方法:

  private okhttp3.Call createRawCall() throws IOException {
    //首先創(chuàng)建出okhttp3.Request 
    Request request = serviceMethod.toRequest(args);
    //通過(guò)request構(gòu)建 okhttp3.Call
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }

那么從這里開(kāi)始,這些任務(wù)又回到了ServiceMethod這個(gè)類中了!所以說(shuō)ServiceMethod完全服務(wù)于Http請(qǐng)求響應(yīng)的相關(guān)過(guò)程!

    /** Builds an HTTP request from method arguments. */
  Request toRequest(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();
  }

它構(gòu)建出一個(gè)RequestBuilder的類,這也是第五個(gè)需要講解的類了!看名字都知道它就是用來(lái)構(gòu)建RequestBuilder啦!,構(gòu)建出Builder之后,注意這次是帶上具體的參數(shù)過(guò)來(lái)的,所以它會(huì)進(jìn)行參數(shù)的封裝,構(gòu)建出最終要去請(qǐng)求的url!!之前有說(shuō)過(guò)對(duì)應(yīng)的每個(gè)參數(shù)注解已經(jīng)封裝到ParameterHandler這個(gè)類中了,這里就需要遍歷parameterHandlers這個(gè)數(shù)組,完成對(duì)每一個(gè)參數(shù)的具體賦值,賦值其實(shí)也很簡(jiǎn)單,就是依次調(diào)用各個(gè)ParameterHandlerapply(requestBuilder, arg)方法,apply()方法其實(shí)就是調(diào)用之前構(gòu)建好的Convert將對(duì)應(yīng)的參數(shù)(arg)解析成Request里面具體需要的對(duì)象!里面StringConvert居多!比如之前說(shuō)到的@Body的情況(第一部分的結(jié)尾)!,因?yàn)?code>Body你也可以傳入一個(gè)Bean對(duì)象,所以不一定使用的是StringConvert,這里它會(huì)通過(guò)nextRequestBodyConverter()遍歷尋找合適Convert。

Convert.png

比如說(shuō)調(diào)用了GsonRequestBodyConverter中的convert方法完成相關(guān)解析:

      @Override 
      public RequestBody convert(T value) throws IOException {
        Buffer buffer = new Buffer();
        Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
        JsonWriter jsonWriter = gson.newJsonWriter(writer);
        adapter.write(jsonWriter, value);
        jsonWriter.close();
        return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
      }

接著就是調(diào)用requestBuilder.build()的方法了!

Request build() {
            //1.構(gòu)建HttpUrl
            HttpUrl url;
            HttpUrl.Builder urlBuilder = this.urlBuilder;
            if (urlBuilder != null) {
              url = urlBuilder.build();
            } else {
              // No query parameters triggered builder creation, just combine the relative URL and base URL.
              url = baseUrl.resolve(relativeUrl);
              if (url == null) {
                throw new IllegalArgumentException(
                    "Malformed URL. Base: " + baseUrl + ", Relative: " + relativeUrl);
              }
            }
            2.構(gòu)建RequestBody
            RequestBody body = this.body;
            if (body == null) {
              // Try to pull from one of the builders.
              if (formBuilder != null) {
                body = formBuilder.build();
              } else if (multipartBuilder != null) {
                body = multipartBuilder.build();
              } else if (hasBody) {
                // Body is absent, make an empty body.
                body = RequestBody.create(null, new byte[0]);
              }
            }

            MediaType contentType = this.contentType;
            if (contentType != null) {
              if (body != null) {
                body = new ContentTypeOverridingRequestBody(body, contentType);
              } else {
                requestBuilder.addHeader("Content-Type", contentType.toString());
              }
            }

            return requestBuilder
                .url(url)
                .method(method, body)
                .build();
          }

到這里Request終于是構(gòu)建好了!接下來(lái)是真正的去創(chuàng)建okhttp3.Call了!

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

這里其實(shí)最終使用的是Retrofit里面構(gòu)建的okhttp3.Call.Factory

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

Response

最后終于到結(jié)果的位置了,這個(gè)Response也是我們要介紹的第六個(gè)對(duì)象了!它算是okhttp.Response的一個(gè)裝飾類吧!也是最后返回給調(diào)用者使用的類!

  Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();

    // Remove the body's source (the only stateful object) so we can pass the response along.
    rawResponse = rawResponse.newBuilder()
        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
        .build();

    int code = rawResponse.code();
    if (code < 200 || code >= 300) {
      try {
        // Buffer the entire body to avoid future I/O.
        ResponseBody bufferedBody = Utils.buffer(rawBody);
        return Response.error(bufferedBody, rawResponse);
      } finally {
        rawBody.close();
      }
    }

    if (code == 204 || code == 205) {
      return Response.success(null, rawResponse);
    }

    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
      T body = serviceMethod.toResponse(catchingBody);
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
      // If the underlying source threw an exception, propagate that rather than indicating it was
      // a runtime exception.
      catchingBody.throwIfCaught();
      throw e;
    }
  }

無(wú)論是同步或者異步的方法,最后總會(huì)通過(guò)parseResponse()的方法將okhttp3.Response包裝為Response對(duì)象返回!!而具體的解析又會(huì)交給ServiceMethod里面的的toResponse()去處理!!

    T toResponse(ResponseBody body) throws IOException {
        return responseConverter.convert(body);
      }

其實(shí)就是調(diào)用之前確認(rèn)好的responseConverter去解析對(duì)應(yīng)的Body!
到這里,http請(qǐng)求完成,結(jié)果也被封裝為指定的對(duì)象返回了!

總結(jié)

Retrofit.png

1、Call(接口):向服務(wù)器發(fā)送請(qǐng)求并返回響應(yīng)的調(diào)用;
2、CallAdapter(接口):Call的適配器,將Call適配為不同的類型返回(Call、Observable);
3、CallBack(接口):顧名思義Call的回調(diào),Call執(zhí)行時(shí)的回調(diào);
4、Converter(接口):數(shù)據(jù)轉(zhuǎn)換器,將一個(gè)對(duì)象轉(zhuǎn)化另外一個(gè)對(duì)象;
5、CallAdapter.Factory(接口):CallAdapter的工廠,通過(guò)get()方法獲取CallAdapter,使用adapt()執(zhí)行對(duì)應(yīng)的Call請(qǐng)求;
6、Converter.Factory(抽象類) : 數(shù)據(jù)轉(zhuǎn)換器Converter的工廠;

  • responseBodyConverter:將ResponseBody轉(zhuǎn)換為具體的對(duì)象。
  • requestBodyConverter : 將對(duì)應(yīng)的BodyPartPartMap注解轉(zhuǎn)換為RequestBody(OkHttp3),以便http請(qǐng)求的時(shí)候使用。
  • StringConverter:將FieldFieldMap 值,HeaderPathQuery,和QueryMap值轉(zhuǎn)化為String,以便http請(qǐng)求的時(shí)候使用。

7、ParameterHandler : 方法參數(shù)的處理類;

8、ServiceMethod :請(qǐng)求方法的生成處理類,用于確定CallAdapterResponseConverter,生成具體的請(qǐng)求Request,解析對(duì)應(yīng)的Response數(shù)據(jù),算是一個(gè)灰常重要的類了;
9、Platform:確認(rèn)不同運(yùn)行環(huán)境的類;
10、OkHttpCall :實(shí)現(xiàn)Call接口,是okhttp3.Call的代理類,獲取傳入的Call,通過(guò)Retrofit.callFactory執(zhí)行Call請(qǐng)求,獲取數(shù)據(jù)并使用ResponseConverter進(jìn)行解析;

再回到之前說(shuō)的那些問(wèn)題上:
1、Retrofit是使用注解確定對(duì)應(yīng)的請(qǐng)求方式和參數(shù)的,那么具體的url是怎么產(chǎn)生出來(lái)的的呢?
(ServiceMethod里面的相關(guān)處理)
2、我們定義的是一個(gè)接口,那么Retrofit又是怎么生成對(duì)應(yīng)的實(shí)現(xiàn)類的呢?
(動(dòng)態(tài)代理)
3、網(wǎng)絡(luò)請(qǐng)求V2.0開(kāi)始統(tǒng)一使用OkHttp了,那么異步回調(diào)到主線程是如何實(shí)現(xiàn)的?
(MainThreadExecutor)
4、同一個(gè)方法,支持Call<T>的返回類型,又可以支持Observable<T>
的返回類型,這個(gè)又是如何實(shí)現(xiàn)的?
(確定對(duì)應(yīng)CallAdapter!)
5、同一個(gè)方法,支持不同的轉(zhuǎn)換(Gson、Jackson、Moshi、FastJson等等),這個(gè)又是如何實(shí)現(xiàn)的呢?
(確定對(duì)應(yīng)的Convert!)

搞了這么久,學(xué)習(xí)到什么呢?從一開(kāi)始的一臉懵逼到最后的暗自竊喜,這也算是一種進(jìn)步吧!其中不得不提的是各種設(shè)計(jì)模式的使用,模塊間解耦和擴(kuò)展的思想!創(chuàng)建型的抽象工廠模式、Builder模式;結(jié)構(gòu)性的代理模式、adapter模式、裝飾者模式;行為性的責(zé)任鏈模式等等。。

---- Edit By Joe ----

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 簡(jiǎn)介 剛接觸Retrofit的時(shí)候,就寫了一篇簡(jiǎn)單的使用介紹:Retrofit 2.0基本使用方法,算是對(duì)Retr...
    Whyn閱讀 2,887評(píng)論 4 24
  • Retrofit是squareup公司的開(kāi)源力作,和同屬squareup公司開(kāi)源的OkHttp,一個(gè)負(fù)責(zé)網(wǎng)絡(luò)調(diào)度,...
    藍(lán)灰_q閱讀 41,870評(píng)論 23 281
  • 適配器模式上一篇文章我們已經(jīng)分析了Retrofit解析注解封裝進(jìn)ServiceMethod的流程,讀者在這里要記住...
    andcoder閱讀 681評(píng)論 0 2
  • 一、什么是Retrofit A type-safe HTTP client for Android and Jav...
    andcoder閱讀 788評(píng)論 2 3
  • 用齊一的歌詞描述這一年就是:這個(gè)年紀(jì)的我們愛(ài)情跟不上分開(kāi)的節(jié)奏,這個(gè)年紀(jì)的我們更珍惜難得的自由,這個(gè)年紀(jì)的我們比起...
    木子言寺月閱讀 534評(píng)論 0 1