android中Retrofit2源碼解析(新版本)

android中Retrofit源碼解析(新版)

在android開(kāi)發(fā)中我們?cè)鷳?yīng)用發(fā)起網(wǎng)絡(luò)請(qǐng)求的時(shí)候,不免需要使用android對(duì)網(wǎng)絡(luò)請(qǐng)求的封裝,它提供了對(duì)http協(xié)議底層的抽象,我們可以通過(guò)它提供的方法直接調(diào)用http請(qǐng)求。在android2.2版本及其以前的版本使用HttpClient,在android2.3版本及其之后我們使用了httpUrlConnection,而且在6.0之后android移除了httpClient,我們?cè)诟甙姹镜腁PI中只能使用HttpUrlConnection了。

1.1 retrofit和OkHttp的關(guān)系

但是實(shí)際情況是使用了httpUrlConnection還是很繁瑣,我們還是要去考慮超時(shí)時(shí)間,服務(wù)器異常情況、數(shù)據(jù)流轉(zhuǎn)為實(shí)體對(duì)象這些煩惱。所以有了對(duì)android內(nèi)置的HttpUrlConnection or httpClient的包裝,讓我們專心處理業(yè)務(wù)邏輯。oKHttp就誕生了,android4.4版本以后都內(nèi)置了oKHttp了,而我們要討論的retrofit就是再次對(duì)okHttp的包裝,豐富了很多強(qiáng)大的功能,比如能和Rxjava這個(gè)流行的框架結(jié)合,返回結(jié)果能回調(diào)到UI線程等。oKHttp的源碼涉及到了對(duì)阻塞隊(duì)列,線程池的應(yīng)用,我們下一節(jié)進(jìn)行探討。

1.2 retrofit的本質(zhì)

retrofit的本質(zhì)就是應(yīng)用了大量的設(shè)計(jì)模式對(duì)Okhttp進(jìn)行了封裝,加入了網(wǎng)絡(luò)數(shù)據(jù)轉(zhuǎn)換、網(wǎng)絡(luò)請(qǐng)求回調(diào)、網(wǎng)絡(luò)請(qǐng)求適配這幾個(gè)主要的功能。它本身肯定不會(huì)去發(fā)請(qǐng)求的,發(fā)請(qǐng)求交給了OkHttp,它只對(duì)調(diào)用方式和返回結(jié)果進(jìn)行處理其他的不關(guān)它的事。為什么要去研究retrofit的源碼呢?因?yàn)樗庋b的方式解耦性很高,功能調(diào)用十分簡(jiǎn)潔,可以參照它對(duì)我們的代碼也能進(jìn)行改造。

1.3 源碼解析(retrofit:2.4.0)

1.3.1 retrofit的創(chuàng)建

一起打開(kāi)IDE閱讀源碼更虛?。etrofit的創(chuàng)建是整個(gè)框架的入口,它肯定會(huì)提前準(zhǔn)備好很多看不懂的變量進(jìn)行初始化,但是這不能阻擋我們,往后看就能理解它代表的含義了。根據(jù)官方的文檔,retrofit的創(chuàng)建使用了建造者模式。

Retrofit retrofit = new Retrofit.Builder() 
//基本URL
.baseUrl("https://www.baidu.com") 
//網(wǎng)絡(luò)請(qǐng)求適配器
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
//網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)轉(zhuǎn)換器
.addConverterFactory(GsonConverterFactory.create()) 
//網(wǎng)絡(luò)請(qǐng)求執(zhí)行器
.client(new OkHttpClient())       
.build(); 

所謂建造者模式就是有builder關(guān)鍵字的方式,就是這么簡(jiǎn)單!當(dāng)然這是一個(gè)玩喜,建造者模式和我們以前 get/set 類的屬性沒(méi)有什么本質(zhì)的區(qū)別,主要是將這些set方法全部提取出來(lái) 形成一個(gè)抽象類或者內(nèi)部類,然后在一個(gè)建造者類里面去設(shè)置屬性,返回一個(gè)實(shí)體類對(duì)象,列如:

public abstract Builder{
public void BulidProperty(String url);
}
public class RealBuilder extends Builder{
private RealObject object;
public void BulidProperty(String url){
    object.SetProperty(url);
     }
 public RealObject build(){
     return RealObject;
     }
}

簡(jiǎn)單的思想大概是這樣的,具體的我們可以看一下Retrofit中的源碼。第一行代碼

//第一行代碼
Retrofit retrofit = new Retrofit.Builder() 

很明顯這個(gè)Builder是一個(gè)Retrofit的內(nèi)部類,那說(shuō)明建造者不是繼承了抽象類,而是使用了內(nèi)部類來(lái)設(shè)置屬性。來(lái)看一下這個(gè)內(nèi)部類,如下:


public static final class Builder { 
    //不知道這是什么東東先放在一邊
    private final Platform platform;
    //很明顯出現(xiàn)了okhttp,就知道它肯定負(fù)責(zé)去發(fā)請(qǐng)求
    private okhttp3.Call.Factory callFactory;  
    // 8必多說(shuō) 大家都懂
    private HttpUrl baseUrl;
    //很明顯它是存數(shù)據(jù)轉(zhuǎn)換用的,但是為什么搞一個(gè)list 懵b?
    private final List<Converter.Factory> converterFactories = new ArrayList<>(); 
    //很明顯它存網(wǎng)絡(luò)適配器用的,再次疑問(wèn)這個(gè)網(wǎng)絡(luò)適配器是什么東東?
    private final List<CallAdapter.Factory> adapterFactories = new ArrayList<>(); 
    //很明顯他是一個(gè)回調(diào)執(zhí)行器,這個(gè)有什么用呢?
    private Executor callbackExecutor; 
    //這肯定是校驗(yàn)Flag目前不知道有什么用
    private boolean validateEagerly;

里面看不懂的變量主要有adapterFactories存的網(wǎng)絡(luò)適配器工廠(CallAdapter.Factory),很明顯他后面會(huì)使用工廠設(shè)計(jì)模式去產(chǎn)生CallAdapter的對(duì)象,至于數(shù)據(jù)轉(zhuǎn)換器(converter)我們都知道http請(qǐng)求返回來(lái)的是數(shù)據(jù)流InputStream方式的,轉(zhuǎn)為Json,XML之類需要一個(gè)轉(zhuǎn)換器,類似于一個(gè)double轉(zhuǎn)int的工具類。

  • 網(wǎng)絡(luò)適配器的含義及其作用:網(wǎng)絡(luò)適配器是我自己給他的定義,從命名上來(lái)看是叫:CallAdapter,Call肯定是來(lái)發(fā)請(qǐng)求的,Adapter憶往昔崢嶸歲月,在listView里面是界面和數(shù)據(jù)的橋梁,同理這里的CallAdapter應(yīng)該是客戶端和網(wǎng)絡(luò)之間橋梁。客戶端發(fā)請(qǐng)求的操作肯定是要通過(guò)它的。如圖:
image.png

這樣我們就可以清楚的看到了CallAdapter的作用了,它對(duì)OkHttp進(jìn)行包裝,我們調(diào)用請(qǐng)求方法的時(shí)候都要通過(guò)它。它同時(shí)持有了okHttp對(duì)象和回調(diào)執(zhí)行器的對(duì)象,這樣它通過(guò)Okhttp拿到數(shù)據(jù)之后,用回調(diào)執(zhí)行器回調(diào)。

  • 回調(diào)執(zhí)行器:回調(diào)執(zhí)行器就是在拿到數(shù)據(jù)結(jié)果之后,我們?cè)趺捶祷亟Y(jié)果的問(wèn)題,主要的問(wèn)題就是由于是異步請(qǐng)求,我們想要使用數(shù)據(jù)填充界面,需要切換到主線程。
  //再看看構(gòu)造函數(shù)
  Retrofit retrofit = new Retrofit.Builder() 

這個(gè)內(nèi)部類的構(gòu)造函數(shù)做了些什么內(nèi)容?就一句調(diào)用自己的有參構(gòu)造函數(shù),佛了!

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

我們來(lái)看看這個(gè)有參構(gòu)造函數(shù)和Platform類是什么東東:

    //Platform類
class Platform {
  private static final Platform PLATFORM = findPlatform();
  static Platform get() {
  //f返回一個(gè)實(shí)例就完事了
    return PLATFORM;
  }
  //根據(jù)不同運(yùn)行平臺(tái)返回對(duì)應(yīng)的Platforem對(duì)象 
     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) {
    }
    return new Platform();
  }

看到這里我們就明白了,他根據(jù)運(yùn)行的平臺(tái)不同來(lái)返回相應(yīng)的對(duì)象,我們這里只分析 new Adnroid();看看里面有什么內(nèi)容:

static class Android extends Platform {
 //一個(gè)默認(rèn)的回調(diào)執(zhí)行器
    @Override
     public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }
    //很明顯 很熟悉 !創(chuàng)建了一個(gè)默認(rèn)的CallAdapter(網(wǎng)絡(luò)適配器),而且傳入了一個(gè)回調(diào)執(zhí)行器(回調(diào)執(zhí)行器可以自定義,不然就是用默認(rèn)綁定主線程)
    @Override 
    CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }
     static class MainThreadExecutor implements Executor {
     //給力 綁定了主線程的 looper (關(guān)于Handler的詳細(xì)內(nèi)容可以自己查詢)
      private final Handler handler = new Handler(Looper.getMainLooper());
      @Override 
      public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }

到此我們明白了 Platfrom的作用了,它提供了一個(gè)默認(rèn)的CallAdapter.Factory用來(lái)生產(chǎn)CallAdapter,還提供了一個(gè)綁定主線程的默認(rèn)回調(diào)執(zhí)行器。

再次回頭看創(chuàng)建Retrofit的其他代碼

Retrofit retrofit = new Retrofit.Builder() 
//基本URL
.baseUrl("https://www.baidu.com")
//可以自定義回調(diào)執(zhí)行器,否則默認(rèn)回調(diào)到主線程
.callbackExecutor("xxxx")
//網(wǎng)絡(luò)請(qǐng)求適配器
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
//網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)轉(zhuǎn)換器
.addConverterFactory(GsonConverterFactory.create()) 
//網(wǎng)絡(luò)請(qǐng)求執(zhí)行器
.client(new OkHttpClient())       
.build(); 

baseUrl、add這些方法是給內(nèi)部類屬性賦值,我們主要來(lái)看build()方法。

 public Retrofit build() {
    //可見(jiàn)baseUrl 是必須的 使用的時(shí)候要注意
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
      //很明顯 生產(chǎn)網(wǎng)絡(luò)請(qǐng)求的工廠,如果你不傳入自定義的okHttp對(duì)象,他會(huì)默認(rèn)使用okHttpclient
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }
      //如果沒(méi)有自定義,加入剛剛說(shuō)過(guò)的默認(rèn)調(diào)到到主線程
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }
      //將傳入到內(nèi)部類callAdapter copy一份 傳入到retrofit的構(gòu)造函數(shù)
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
        //它會(huì)添加一個(gè)默認(rèn)的網(wǎng)絡(luò)適配器,這個(gè)網(wǎng)絡(luò)適配器它持有callbackExecutor回調(diào)執(zhí)行器的對(duì)象。
      callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
      //很明顯類似adapterFactories 添加了一個(gè)默認(rèn),再copy一份到 retrofit的構(gòu)造函數(shù)中。
      List<Converter.Factory> converterFactories =new ArrayList<>(1 + this.converterFactories.size());
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);
      //返回retrofit的實(shí)例對(duì)象就完事了
      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
    }
  }

這里的代碼都很簡(jiǎn)單,但是有幾個(gè)疑問(wèn)?為什么這個(gè)adapterFactories和converterFactories都是list呢,它里面都存了些什么。

  • adapterFactories: 一個(gè)list集合,存儲(chǔ)了網(wǎng)絡(luò)適配器工廠,根據(jù)上面的代碼我們可以看到它里面的內(nèi)容是:先添加了自定義的、后面添加了一個(gè)默認(rèn)的,總共兩個(gè)元素。在Retrofit中提供了四種CallAdapterFactory: ExecutorCallAdapterFactory(默認(rèn))、GuavaCallAdapterFactory、Java8CallAdapterFactory、RxJavaCallAdapterFactory。其他的沒(méi)有用過(guò),但是看到Rxjava我們就知道了,如果想要和Rxjava結(jié)合起來(lái)這個(gè)RxJavaCallAdapterFactory必須添加進(jìn)去
//通過(guò)這個(gè)添加進(jìn)去,是不是可以添加多個(gè)呢?
Retrofit retrofit = new Retrofit.Builder() 
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
//我們還可以添加
// adapterFactories里面順序
// 自定義1-自定義2-.....默認(rèn)。
addCallAdapterFactory(Java8CallAdapterFactory.create())
addCallAdapterFactory(GuavaCallAdapterFactory.create())
//converter 同理啊鐵子!
.addConverterFactory(GsonConverterFactory.create()) 

也不會(huì)有問(wèn)題,因?yàn)槲覀兙W(wǎng)絡(luò)請(qǐng)求都是多種多樣的,上面已經(jīng)說(shuō)得我們發(fā)請(qǐng)求就是操作CallAdapter,所以有結(jié)果返回的時(shí)候也需要通過(guò)CallAdapter。有時(shí)候我們需要Rxjava的observeable這種返回對(duì)象,有時(shí)候我們還是需要Call這種類型的返回對(duì)象,所以他需要一個(gè)list去組裝對(duì)應(yīng)的CalladapterFactory,Call代表了默認(rèn)CallAapter返回出來(lái)的的,Observable代表了我們添加進(jìn)去的RxJavaCallAdapter返回出來(lái)的。同理我們需要從CallAdapter得到想要的數(shù)據(jù)類型,converterFactories也需要多個(gè)。

    @GET
    //我想要Observable 需要相應(yīng)的的CallAdapter
   Observable<ResponseBody> download(@Url String url);
    @GET
        //我想要Call 默認(rèn)的CallAdapter就行
        //同時(shí)還需要將結(jié)果變成IModel 怎么說(shuō)吧你
    Call<IModel>download(@Url String url);

總結(jié):我們清楚的看到了,retrofit的創(chuàng)建過(guò)程,主要的內(nèi)容就是四個(gè)器的初始化,網(wǎng)絡(luò)適配器(CallAdapter),數(shù)據(jù)轉(zhuǎn)換器(conver),請(qǐng)求執(zhí)行器(oKHttp),回調(diào)執(zhí)行器(callbackExecutor)。關(guān)注點(diǎn)在我們發(fā)請(qǐng)求操作都是CallAdapter,它肯定持有其他三個(gè)的引用,就像吃雞里面他是我們的角色,其他的是M4,頭盔 藥品等。

1.3.2 創(chuàng)建網(wǎng)絡(luò)請(qǐng)求接口的實(shí)例。

對(duì)我們的的注解定義的接口方法進(jìn)行解析,從而創(chuàng)建實(shí)例,有點(diǎn)迷惑?什么實(shí)例,干什么用的?我們繼續(xù)往下看。

retrofit.create(RetrofitService.class);

看到這種傳入.class的 ,我們可以想到肯定會(huì)用到反射。

 public <T> T create(final Class<T> service) {
    //校驗(yàn)接口正確性,是否符合注解規(guī)則
    Utils.validateServiceInterface(service);
    //validateEagerly 這個(gè)變量主要是作用是 是否提前加入緩存
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    //很明顯這里使用了動(dòng)態(tài)代理模式
    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 {
              //如果是java里面的基類不做處理 
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            // 這個(gè)沒(méi)什么用android平臺(tái)默認(rèn)返回的是false的
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
           //非常重要的3行代碼
           //解析方法的返回參數(shù) 請(qǐng)求參數(shù) 請(qǐng)求類型等
            ServiceMethod<Object, Object> serviceMethod =(ServiceMethod<Object, Object>) loadServiceMethod(method);
            //很明顯OkHttp就知道他是一個(gè)網(wǎng)絡(luò)執(zhí)行器
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            //很明顯他 肯定是調(diào)用了callAdapter  
            return serviceMethod.adapt(okHttpCall);
          }
        });
  }

這里的代碼稍微有一丟丟復(fù)雜,主要理解代理模式。代理代理,不知道大家是否知道代購(gòu)。比如你想買一件surpene的衣服,當(dāng)然superme肯定買不起,只能買買faker。又拉下不臉,找了一個(gè)代購(gòu)。

image.png

代理類會(huì)獲取被代理類的所有方法,并返回一個(gè)被代理類的對(duì)象,這個(gè)對(duì)象就是虛擬的你,通過(guò)它去購(gòu)買需要的商品。Proxy.newProxyInstance(xxx)是固定用法,只要傳入xxx.class參數(shù)就行。

     //固定格式
     ClassLoader classLoader =Shop.class.getClassLoader();
     //固定格式,三個(gè)參數(shù),傳入Shop.class參數(shù),獲取所有方法,返回代理對(duì)象。
     Shop shopProy = (Shop) Proxy.newProxyInstance(classLoader, new Class[]{IShop.class}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //回調(diào)原來(lái)類的方法,該怎么做就怎么做
                Object result = method.invoke(proxy,args);
                //也可以自己實(shí)現(xiàn) 不回調(diào)原來(lái)的方法。
                //.............................
                return result;
            }
        });

這里的Invoke方法,就是代理方法的實(shí)現(xiàn),method.invoke()代表了回調(diào)原來(lái)的方法,這里也可以自己去實(shí)現(xiàn)方法,只要返回對(duì)應(yīng)的類型。代理模式優(yōu)點(diǎn)就是提供了一個(gè)攔截接口,不管你什么方法調(diào)用都會(huì)先進(jìn)入Invoke。具體內(nèi)容可以學(xué)習(xí)JAVA反射來(lái)加深印象。

  .........................................
  //validateEagerly 這個(gè)變量主要是作用是 是否提前加入緩存
   if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    //很明顯這里使用了動(dòng)態(tài)代理模式
    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 {
              //.............................
           //非常重要的3行代碼
           //解析方法的返回參數(shù) 請(qǐng)求參數(shù) 請(qǐng)求類型等 關(guān)鍵代碼1
            ServiceMethod<Object, Object> serviceMethod =(ServiceMethod<Object, Object>) loadServiceMethod(method);
            //很明顯OkHttp就知道他是一個(gè)網(wǎng)絡(luò)執(zhí)行器 關(guān)鍵代碼2
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            //很明顯他 肯定是調(diào)用了callAdapter   關(guān)鍵代碼3
            return serviceMethod.adapt(okHttpCall);
            }

回到代理創(chuàng)建接口實(shí)例的方法中,我們創(chuàng)建接口的時(shí)候都是只寫了方法名,沒(méi)有具體的實(shí)現(xiàn),所以在代理對(duì)象并不能回調(diào),它只能自己去實(shí)現(xiàn)而且還要返回你要想的結(jié)果類型。苦b?。?/p>

public interface RetrofitService {
  //沒(méi)有方法體 只有名字 怎么破(只能靠retrofit給我們實(shí)行)
   @GET
  Observable<ResponseBody> download(@Url String url);
   // 沒(méi)有方法體,只有名字 怎么破
   @GET
   Call<ResponseBody>download(@Url String url);
}

在retrofi中,利用了ServceMehod這個(gè)類來(lái)進(jìn)行實(shí)現(xiàn)方法體,它會(huì)獲取到接口方法的參數(shù),返回值類型,請(qǐng)求方式等所有參數(shù)??匆幌玛P(guān)鍵代碼1,loadServiceMethod()?。?/p>

 ServiceMethod<?, ?> loadServiceMethod(Method method) {
   //搞個(gè)緩存啊 美滋滋
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;
    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
      //緩存里面沒(méi)有,說(shuō)明是第一次調(diào)用,安排一下,并且加入緩存
        result = new ServiceMethod.Builder<>(this, method).build();//我只是一個(gè)建造者,傳入了retrofit的對(duì)象,擁有了adapterFactorese等所有屬性。
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

代碼很簡(jiǎn)單,對(duì)調(diào)用的方法做一個(gè)緩存,第一次調(diào)用的時(shí)候才會(huì)去解析方法,其他情況下會(huì)使用緩存。同時(shí)我們也應(yīng)該知道validateEagerly這個(gè)Flag的作用了,如果你設(shè)置為true會(huì)創(chuàng)建動(dòng)態(tài)代理對(duì)象的時(shí)候?qū)⑺械姆椒ń馕鼍彺?,否則就只會(huì)在第一次調(diào)用的時(shí)候去緩存。
雖然已經(jīng)知道了ServiceMethod會(huì)對(duì)我們請(qǐng)求的方法進(jìn)行一頓瞎x操作,各種解析分析組裝,但是我們還要要去看看實(shí)況,它采用了建造者模式(builder),直接看.build()方法。

 public ServiceMethod build() {
     ..........................................//
     //根據(jù)返回值類型,在adapterFactories的list里面去尋找CallAdapter,如observeable,就會(huì)尋找RxjavCallAdapter.Factory 工廠模式產(chǎn)生CallAdapter 的對(duì)象。
      callAdapter = createCallAdapter();
      //獲取返回值中的數(shù)據(jù)類型
      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?");
      }
      //根據(jù)CallAdapter的返回的值中的數(shù)據(jù)類型(如: Call<Bean> download(), 就會(huì)根據(jù) ‘ Bean’去尋找Gson轉(zhuǎn)換器)去遍歷converterList找轉(zhuǎn)換器,Converter 的對(duì)象。
      responseConverter = createResponseConverter();
      //遍歷方法中的所有注解 一頓操作保存起來(lái)。
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }
      int parameterCount = parameterAnnotationsArray.length;
      // 保存請(qǐng)求參數(shù)的工具類
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        ..................///
        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        ..................//
        //遍歷方法參數(shù)中的所有注解和變量到parameterHandlers
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }
      .......................//
      //返回一個(gè) ServiceMethod的實(shí)例
      return new ServiceMethod<>(this);
    }

主要作用是根據(jù)方法的返回值類型,獲取相應(yīng)的網(wǎng)絡(luò)適配器、數(shù)據(jù)轉(zhuǎn)換器以及拆卸參數(shù)類型等保存在parameterHandlers中。列如:createCallAdapter會(huì)去遍歷callAdapterFactories找到相應(yīng)的callAdapter。

public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
      //.......................................................
      //根據(jù)返回值遍歷callAdapterFactories
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
     // get返回了一個(gè)CallAdapter對(duì)象
      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }
    
    //這里假設(shè)我們返回值是 Call<Bean> 類型的 ,默認(rèn)的ExecutorCallAdapterFactory會(huì)被匹配到??纯此膅et方法
  @Override
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);
    //給力呀 鐵子 返回了一個(gè) CallAdapter對(duì)象
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }
      // 我就是方法體啊鐵子 
      @Override public Call<Object> adapt(Call<Object> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }

其中Calladapter中的adapt方法就是方法體了。后續(xù)詳細(xì)介紹這個(gè)CallAdapter類。
根據(jù)關(guān)鍵代碼1, loadServiceMethod()返回了一個(gè)ServiceMethod的實(shí)例,它里面包含了你調(diào)用方法的所有信息,包含注解,參數(shù)類型,參數(shù)名,返回值類型等,來(lái)看看它里面主要的屬性:

  final class ServiceMethod<R, T> {
   .............................//
  //這個(gè)是Okhttp的工廠實(shí)例,用來(lái)生產(chǎn)請(qǐng)求call的
  private final okhttp3.Call.Factory callFactory;
  //橋梁callAdapter 實(shí)例 發(fā)請(qǐng)求都是它在操作okhttp
  private final CallAdapter<R, T> callAdapter;
  // 8 必再說(shuō)
  private final HttpUrl baseUrl;
  //數(shù)據(jù)轉(zhuǎn)換器實(shí)例
  private final Converter<ResponseBody, R> responseConverter;
.......................//
//存儲(chǔ)請(qǐng)求參數(shù)的集合
  private final ParameterHandler<?>[] parameterHandlers;

到此Retrofi已經(jīng)實(shí)現(xiàn)了高度的解耦,定義一個(gè)請(qǐng)求方法,我只想調(diào)用一下得到結(jié)果,至于怎么請(qǐng)求的,和怎么轉(zhuǎn)換結(jié)果都不想關(guān)注。retrofit在這里使用了外觀模式,只用定義方法入口(Retrofit.create(YourInterface.Class)),減少了對(duì)內(nèi)部細(xì)節(jié)的依賴,里面發(fā)生了變化,我們也不用擔(dān)心。
繼續(xù)看關(guān)鍵代碼2:

//很明顯這里使用了動(dòng)態(tài)代理模式
    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 {
              //.............................
           //非常重要的3行代碼
           //解析方法的返回參數(shù) 請(qǐng)求參數(shù) 請(qǐng)求類型等 關(guān)鍵代碼1
            ServiceMethod<Object, Object> serviceMethod =(ServiceMethod<Object, Object>) loadServiceMethod(method);
            //很明顯OkHttp就知道他是一個(gè)網(wǎng)絡(luò)執(zhí)行器 關(guān)鍵代碼2
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            //很明顯他 肯定是調(diào)用了callAdapter   關(guān)鍵代碼3
            return serviceMethod.adapt(okHttpCall);
            }

將servcieMethod傳入到oKhttpCall,serviceMethod已經(jīng)把請(qǐng)求參數(shù)拆卸下來(lái)存儲(chǔ)在了parameterHandlers中,OkHttpCall會(huì)取出參數(shù)類型和值進(jìn)行組裝請(qǐng)求。

final class OkHttpCall<T> implements Call<T> {
  private final ServiceMethod<T, ?> serviceMethod;//含有所有網(wǎng)絡(luò)請(qǐng)求參數(shù)類型等等
  private final @Nullable Object[] args;//請(qǐng)求參數(shù)的值

  private volatile boolean canceled;//取消請(qǐng)求Falg

  @GuardedBy("this")
  private @Nullable okhttp3.Call rawCall;//真正發(fā)請(qǐng)求的Okhttp
............................................//

  }

OkHttpCall里面有了okhttp對(duì)象,使用它來(lái)進(jìn)行發(fā)請(qǐng)求操作,具體我們往下看。
關(guān)鍵代碼3:

        //很明顯他 肯定是調(diào)用了callAdapter   關(guān)鍵代碼3
            return serviceMethod.adapt(okHttpCall);
    // 在ServiceMethod中adapt 調(diào)用了callAdapter
    final class ServiceMethod {
    ..................................//
      T adapt(Call<R> call) {
          return callAdapter.adapt(call);
        }
   ...............................//     
     }      

將生產(chǎn)好的Call對(duì)象傳入到adapter中,然后開(kāi)始實(shí)現(xiàn)方法體.
這里結(jié)合實(shí)例來(lái)看:

    //我想要Call類型的返回值,使用默認(rèn)CallAdapter的就行了
    @GET
    Call<Model>download(@Url String url);
    
    //使用 mRetrofitService.downloadADfile(xxx),就是在調(diào)用  serviceMethod.adapt(okHttpCall);
    Call<Model> call = mRetrofitService.downloadADfile("www.kawayi.com");   

我們?cè)谶@里的 "call = "返回的是什么呢?來(lái)看一哈肯定很簡(jiǎn)單。

//根據(jù)剛返回類型'Call' 遍歷CallAdapterFactories循環(huán)出得到默認(rèn)CallAdapter
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }
      //返回了一個(gè)ExecutorCallbackCall對(duì)象 來(lái)看一哈
      @Override public Call<Object> adapt(Call<Object> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }

很顯然返回了一個(gè)ExecutorCallbackCall對(duì)象,ExecutorCallbackCall內(nèi)容并不是很復(fù)雜。

//這里是ExecutorCallbackCall 繼承了Call
static final class ExecutorCallbackCall<T> implements Call<T> {
  //回調(diào)執(zhí)行器,有自定義就用自定義否則就會(huì)使用platform這個(gè)對(duì)象生產(chǎn)出綁定主線程的回調(diào)
  final Executor callbackExecutor;
  //這里傳入的是OkhttpCall
  final Call<T> delegate;
  //構(gòu)造函數(shù),傳入了OkhttpCall,和回調(diào)執(zhí)行器,裝飾模式安排安排
  ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
    this.callbackExecutor = callbackExecutor;
    this.delegate = delegate;
  }
  //執(zhí)行異步請(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) {
          //回調(diào)執(zhí)行器 切換線程
        callbackExecutor.execute(new Runnable() {
          @Override public void run() {
            if (delegate.isCanceled()) {
              callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
            } else {
              callback.onResponse(ExecutorCallbackCall.this, response);
            }
          }
        });
      }
     .......................//
}

代碼很簡(jiǎn)單,顯然CallAdapter的內(nèi)部類ExecutorCallbackCall擁有okhttp和回調(diào)執(zhí)行器,所有的一切操作都在是它在執(zhí)行了。這里使用了裝飾模式,加強(qiáng)了okhttCall。裝飾模式:就是不改變類文件和使用繼承的情況下,動(dòng)態(tài)地?cái)U(kuò)展一個(gè)對(duì)象的功能,是一種代替繼承的方案。


image.png

C和A都繼承了B,但C里面有A的對(duì)象,所以他可以調(diào)用A的方法,而且能添加一些A中沒(méi)有的功能。如:

  
  static final class ExecutorCallbackCall<T> implements Call<T> {
   ......................................//
    //ExeCutorCallbackCall和delegate都繼承了Call,但ExeCutorCallbackCall有回調(diào)執(zhí)行,取消請(qǐng)求這些功能,得到了加強(qiáng)。
    final Call<T> delegate;

這里的delegate得到了加強(qiáng),擁有了切換線程的功能。

總結(jié):retrofit.create(RetrofitService.class),使用了動(dòng)態(tài)代理創(chuàng)建RetrofitService對(duì)象,并且對(duì)它接口中的方法進(jìn)行了實(shí)現(xiàn),根據(jù)返回值的類型,尋找CallAdapter和converter并且拆卸請(qǐng)求參數(shù),組裝請(qǐng)求,最后返回了Call的對(duì)象。

1.3.3 返回值執(zhí)行網(wǎng)絡(luò)請(qǐng)求

根據(jù)實(shí)例來(lái)看源碼:


//我想要Call類型的返回值,使用默認(rèn)CallAdapter的就行了 
@GET Call<Model>download(@Url String url); 
//實(shí)際上就是在調(diào)用serviceMethod.adapt(okHttpCall); 
Call<Model> call = mRetrofitService.downloadADfile("www.kawayi.com");
//發(fā)一個(gè)異步請(qǐng)求。
 call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {

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

根據(jù)剛剛分析的代碼可以知道,返回的call對(duì)象是ExecutorCallbackCall的實(shí)例,enque執(zhí)行異步請(qǐng)求的,就會(huì)調(diào)用ExecutorCallbackCall的enque方法。

//這里是ExecutorCallbackCall 繼承了Call
static final class ExecutorCallbackCall<T> implements Call<T> {
  //執(zhí)行異步請(qǐng)求
  @Override public void enqueue(final Callback<T> callback) {
    checkNotNull(callback, "callback == null");
    //okhttpCall去執(zhí)行請(qǐng)求,奧給力。
    delegate.enqueue(new Callback<T>() {
      @Override public void onResponse(Call<T> call, final Response<T> response) { 
      //這只是一個(gè)回調(diào)執(zhí)行器,切換線程
        callbackExecutor.execute(new Runnable() {
          @Override public void run() {
            if (delegate.isCanceled()) {
              callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
            } else {
              callback.onResponse(ExecutorCallbackCall.this, response);
            }
          }
        });
      }
     .......................//
}

代碼中可以看到,我們傳入的okHttpCall(serviceMethod.adapt(okHttpCall))會(huì)調(diào)用okttp去執(zhí)行請(qǐng)求,并且用回調(diào)執(zhí)行器回調(diào)okhttp返回的數(shù)據(jù)數(shù)據(jù)。
下面來(lái)看看okHttp具體是怎么處理的

 final class OkHttpCall<T> implements Call<T> {
  private final ServiceMethod<T, ?> serviceMethod;//含有所有網(wǎng)絡(luò)請(qǐng)求參數(shù)類型等等
  @GuardedBy("this")
  private @Nullable okhttp3.Call rawCall;//真正發(fā)請(qǐng)求的Okhttp
............................................//
  //發(fā)一個(gè)異步請(qǐng)求。實(shí)際上是okhttp操作
 @Override public void enqueue(final Callback<T> callback) {
    checkNotNull(callback, "callback == null");
    //okhttp的實(shí)例
    okhttp3.Call call;
    ..............................................\\
   call = rawCall = createRawCall() ;//拿到parameterHandlers的參數(shù),組裝一個(gè)請(qǐng)求   
   ...........................................\\
   //真正的發(fā)一個(gè)請(qǐng)求
  call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
        Response<T> response;
        try {
        //使用數(shù)據(jù)轉(zhuǎn)換器,轉(zhuǎn)換一下就完事了。
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
         try {
         //回到到對(duì)應(yīng)的CallbackCall中,默認(rèn)是ExecutorCallbackCall
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
        
        

OkhttpCall首先先對(duì)請(qǐng)求進(jìn)行一個(gè)組裝,然后賦值給一個(gè)okhttp.Call的對(duì)象。通過(guò)call對(duì)象去發(fā)起請(qǐng)求,中間有異常超時(shí)對(duì)應(yīng)的處理,拿到正確的請(qǐng)求結(jié)果之后,解析數(shù)據(jù),回調(diào)到對(duì)應(yīng)的CallbackCall,默認(rèn)是ExecutorCallbackCall,最后在ExecutorCallbackCall中使用回調(diào)執(zhí)行器再次回調(diào)。

2.1 總結(jié)

1、Retrofit對(duì)oKHttp層層封裝,利用動(dòng)態(tài)代理模式,實(shí)現(xiàn)接口定義的方法。
2、根據(jù)返回值類型匹配對(duì)應(yīng)的CallAdapter,converter,這里使用了策略模式。在對(duì)應(yīng)的callAdapter中使用了裝飾器模式并且返回了一個(gè)加強(qiáng)的Call對(duì)象。
3、利用返回的Call對(duì)象來(lái)發(fā)請(qǐng)求,利用內(nèi)部包裝的OkHttp對(duì)象,執(zhí)行請(qǐng)求。結(jié)果返回之后,converter解析數(shù)據(jù),經(jīng)過(guò)層層回調(diào),到最后回調(diào)執(zhí)行器切換線程。

參考文獻(xiàn)
[1]劉望舒.Android進(jìn)階之光

最后編輯于
?著作權(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)容

  • ??今天我來(lái)記錄一下我對(duì)Retrofit框架的理解。不得不說(shuō),Retrofit的架構(gòu)設(shè)計(jì)極其優(yōu)秀,既保證了使用上的...
    瓊珶和予閱讀 4,540評(píng)論 0 21
  • 適配器模式上一篇文章我們已經(jīng)分析了Retrofit解析注解封裝進(jìn)ServiceMethod的流程,讀者在這里要記住...
    andcoder閱讀 772評(píng)論 0 2
  • 目錄介紹 1.首先回顧Retrofit簡(jiǎn)單使用方法 2.Retrofit的創(chuàng)建流程源碼分析2.1 Retrofit...
    楊充211閱讀 1,171評(píng)論 0 16
  • 花間辭 作者/陳海洲 迎春之花 陽(yáng)光還不夠溫暖,會(huì)有鮮艷的色彩為我們?nèi)∨?會(huì)有一些驚喜打破荒蕪 寒意還未退去,在這...
    陳海洲洹河閱讀 504評(píng)論 0 2
  • 狂風(fēng)忽云雨,夜半驚坐起! 醒來(lái)殘?jiān)?,滿地是狼藉。
    如魚(yú)得水1994閱讀 228評(píng)論 0 0

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