Retrofit2.9.0源碼解析

前言


之前講過了okhttp的超級(jí)概括的原理解析,okhttp以它優(yōu)秀的線程池設(shè)計(jì),任務(wù)隊(duì)列的分配和轉(zhuǎn)化以及基于責(zé)任鏈模式設(shè)計(jì)的5大攔截器的使用被廣大開發(fā)者間接引入。等等,為啥是間接?你點(diǎn)進(jìn)來的時(shí)候相信已經(jīng)有了答案,當(dāng)然是因?yàn)镽etrofit的橫空出世。當(dāng)我們使用okhttp的時(shí)候肯定得去封裝一層,封裝的時(shí)候得考慮到主、子線程的切換,api返回值的轉(zhuǎn)化處理等等。當(dāng)你哼哧哼哧或者嘻嘻哈哈封裝完畢后,某個(gè)小伙伴說他用不習(xí)慣,他更愿意去做成XXXX+YYYY+okhttp的模式。這個(gè)時(shí)候你是選擇把他k.o.還是自己默默按照他的方式再來一套呢?當(dāng)然是選擇retrofit啦,所以retrofit還是一個(gè)增進(jìn)隊(duì)友之間友誼的軟工具。接下來讓我們一步一步的深挖這個(gè)優(yōu)秀的開源框架是怎么讓友誼的小船越走越遠(yuǎn)的。

使用


public class MainActivity extends AppCompatActivity {
    public static final String API_URL = "https://api.github.com";

    public void request(View view) {
        Retrofit retrofit =
                new Retrofit.Builder()
                        .client(new OkHttpClient())
                        .callFactory(new OkHttpClient())
                        .baseUrl(API_URL)
                        //.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                        //.addConverterFactory(GsonConverterFactory.create())
                        .build();

        // Create an instance of our GitHub API interface.
        GitHub github = retrofit.create(GitHub.class);

        // Create a call instance for looking up Retrofit contributors.
        Call<List<Contributor>> call = github.contributors("square", "retrofit");

        // Fetch and print a list of the contributors to the library.
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    List<Contributor> contributors = call.execute().body();
                    Log.e("ss", contributors.toString());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();

    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        request(null);
    }

    public interface GitHub {
        @GET("/repos/{owner}/{repo}/contributors")
        Call<List<Contributor>> contributors(@Path("owner") String owner, @Path("repo") String repo);
    }

    public static class Contributor {
        public final String login;
        public final int contributions;

        public Contributor(String login, int contributions) {
            this.login = login;
            this.contributions = contributions;
        }

        @Override
        public String toString() {
            return "Contributor{" +
                    "login='" + login + '\'' +
                    ", contributions=" + contributions +
                    '}';
        }
    }

}

以上代碼是從官網(wǎng)的sample中拷貝的一段,除了線程那邊,其他差不多都一樣,把代碼原樣拷貝到as項(xiàng)目中是可以直接運(yùn)行的。使用上就說到這里(然而并沒有說啥)。相信大家對Retrofit的使用早就爛熟于心,甚至看完我寫的樣例代碼后,起身怒拍桌子。所以這里就不多贅述,我們開始撕源碼。

retrofit的封裝模式其實(shí)就是將okhttp覆蓋了一層更加友好的調(diào)用方式,它本質(zhì)還是得靠okhttp來執(zhí)行網(wǎng)絡(luò)請求,就像一把劍,如果單有鋒利的劍身,沒有劍柄和劍鞘,雖然也能殺敵,但是首先得自損八百。當(dāng)照顧到使用者習(xí)慣后加上了劍柄和劍鞘,甚至再付個(gè)魔,使用起來肯定事半功倍,但是真正起作用的只有劍身。retrofit和okhttp的愛恨糾葛大概說起來就是下面這張圖:

image-20210423091905259

讀源碼最簡單的方式就是從使用上入手,所以,我們就從上面的樣例代碼中開始,看看Retrofit的工作流程。

Retrofit.build()方法究竟做了什么


retrofit使用的是構(gòu)建模式創(chuàng)建實(shí)例,我們重點(diǎn)看下它最終build的時(shí)候做了哪些事情

  1. 判斷是否有baseUrl

    if (baseUrl == null) {
            throw new IllegalStateException("Base URL required.");
          }
    
  1. 賦值callFactory,這個(gè)callFactory其實(shí)就是okhttpClient

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

    如果沒有值就默認(rèn)給OkHttpClient,使用Retrofit.client(okhttpClient)也是給callFactory賦值

    /**
     * The HTTP client used for requests.
     *
     * <p>This is a convenience method for calling {@link #callFactory}.
     */
    public Builder client(OkHttpClient client) {
      return callFactory(Objects.requireNonNull(client, "client == null"));
    }
    
    /**
     * Specify a custom call factory for creating {@link Call} instances.
     *
     * <p>Note: Calling {@link #client} automatically sets this value.
     */
    public Builder callFactory(okhttp3.Call.Factory factory) {
      this.callFactory = Objects.requireNonNull(factory, "factory == null");
      return this;
    }
    
  2. 賦值callbackExecutor

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

    通過上面的代碼可以看到,如果沒有設(shè)置,就默認(rèn)給出platform.defaultCallbackExecutor(),那這個(gè)默認(rèn)又個(gè)是啥?callbackExecutor究竟是干嘛用的?我們點(diǎn)進(jìn)去康康

    class Platform {
        ...
      @Nullable
      Executor defaultCallbackExecutor() {
        return null;
      }
        ...
    }
    

    Platform,顧名思義,就是平臺(tái),我們初步判斷這個(gè)類其實(shí)就是選擇平臺(tái)用的,但是return null???,直覺告訴我事出反常必有妖,肯定是哪里把這個(gè)方法給重寫了。

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

    果然是這樣,是一個(gè)叫Android的類復(fù)寫了這個(gè)方法,那是在哪里對這個(gè)Platform進(jìn)行賦值了呢?

    public static final class Retrofit.Builder {
        ...
        public Builder() {
              this(Platform.get());
            }
        ...
    }
    

    其實(shí)就是在創(chuàng)建Retrofit的Builder的時(shí)候就已經(jīng)對所選平臺(tái)進(jìn)行了賦值,具體的賦值方法如下

    class Platform {
      private static final Platform PLATFORM = findPlatform();
    
      static Platform get() {
        return PLATFORM;
      }
      private static Platform findPlatform() {
        return "Dalvik".equals(System.getProperty("java.vm.name"))//就是這一行代碼確定了平臺(tái)
            ? new Android() //
            : new Platform(true);
      }
        ...
    }
    

    確定了平臺(tái)后,再看看Android平臺(tái)下是怎么賦值defaultCallbackExecutor的

      static final class Android extends Platform {
          ...
        @Override
        public Executor defaultCallbackExecutor() {
          return new MainThreadExecutor();
        }
          ...
    
        static final class MainThreadExecutor implements Executor {
          private final Handler handler = new Handler(Looper.getMainLooper());
    
          @Override
          public void execute(Runnable r) {
            handler.post(r);
          }
        }
      }
    

    defaultCallbackExecutor方法就是構(gòu)造了一個(gè)MainThreadExecutor的實(shí)例,這個(gè)實(shí)例里面有個(gè)new Handler(Looper.getMainLooper());很熟悉有木有,看到這里我們大概能猜出來了,Retrofit.callbackExecutor這個(gè)成員變量其實(shí)就是一個(gè)用來切換線程的東東,在執(zhí)行了execute方法后會(huì)切換到主線程。

  3. 賦值callAdapterFactories

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

    上述代碼中callAdapterFactories,就是一個(gè)工廠模式,這里是做成了列表,表示能創(chuàng)建不同的callAdapter,這個(gè)callAdapter其實(shí)就是類比到okhttp中的Call,網(wǎng)絡(luò)請求的關(guān)鍵一步(call.equeue(),call.execute())就是由這個(gè)來做的(先這么認(rèn)為,建立一個(gè)概念)。這里要看看最后那行platform.defaultCallAdapterFactories(callbackExecutor),是不是感覺很熟悉,這里其實(shí)就是做了兩件事情,第一步:把你之前在Retrofit.addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build()中添加的RxJava2CallAdapterFactory這個(gè)實(shí)體給放到callAdapterFactories列表中。第二步:將平臺(tái)中默認(rèn)的callAdapterFactory也放在這個(gè)列表中。那么平臺(tái)默認(rèn)的AdapterFactory長啥樣?

    List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
     @Nullable Executor callbackExecutor) {
            DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
            return hasJava8Types
                ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
                : singletonList(executorFactory);
      }
    

    這個(gè)方法中也做了兩件事,首先創(chuàng)建一個(gè)平臺(tái)默認(rèn)的callAdapterFactory(DefaultCallAdapterFactory),然后判斷hasJava8Types,如果為false,就將這個(gè)DefaultCallAdapterFactory放入到列表中并返回。使用singletonList方法是使用定長列表,為了減少內(nèi)存分配(要不人怎么能去寫開源框架呢,什么事情都做到極致??——暗示點(diǎn)贊)。如果為true那就除了DefaultCallAdapterFactory外還要額外加一個(gè)CompletableFutureCallAdapterFactory,那hasJava8Types是何時(shí)被確定下來的呢?

    class Platform {
        ...
        Platform(boolean hasJava8Types) {
        this.hasJava8Types = hasJava8Types;
            ...
        }
    }
    

    上述代碼得知,是通過構(gòu)造方法確認(rèn)的,所以要去Android類下看看Android是怎么確定這個(gè)值的

      static final class Android extends Platform {
        Android() {
          super(Build.VERSION.SDK_INT >= 24);
        }
          ...
      }
    
    
    

    很簡單,只有當(dāng)sdk>=24時(shí)才為true,為什么要做這樣的一個(gè)判斷?因?yàn)閖ava1.8有一個(gè)新特性叫CompletableFuture,這里不去深挖了,感興趣的同學(xué)可以狗哥一下(狗哥一下,就是強(qiáng)大??——暗示點(diǎn)贊)。

  4. 賦值converterFactories

    List<Converter.Factory> converterFactories =
     new ArrayList<>(
                  1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
    
    // 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());
    converterFactories.addAll(this.converterFactories);
    converterFactories.addAll(platform.defaultConverterFactories());
    

    converterFactories就是給服務(wù)端的返回值進(jìn)行一個(gè)轉(zhuǎn)化用的,這里面的代碼做了幾件事情。

    • 創(chuàng)建一個(gè)List<Converter.Factory> converterFactories列表,這個(gè)列表的長度設(shè)置成在build中配置的converterFactories的長度加平臺(tái)中的默認(rèn)ConverterFactories的長度+1
    • 添加BuiltInConverters轉(zhuǎn)換工廠,這里給出了注釋,狗哥翻譯:首先添加內(nèi)置轉(zhuǎn)換器工廠。 這可以防止覆蓋其行為,但也可以確保使用使用所有類型的轉(zhuǎn)換器時(shí)的正確行為。大概意思就是個(gè)內(nèi)置轉(zhuǎn)換器,用來處理一些奇葩的返回,比如Stream,Buffer,Void,甚至kotlin中的Unit
    • 添加用戶自定義的轉(zhuǎn)換工廠
    • 添加平臺(tái)中的轉(zhuǎn)化工廠,這個(gè)和第一步中的platform.defaultConverterFactoriesSize()平臺(tái)工廠列表長度相呼應(yīng),如果平臺(tái)中有轉(zhuǎn)換工廠列表就有size,如果沒有size 就等于0。

    平臺(tái)默認(rèn)工廠列表有哪些?看代碼

    class Platform {
        ...
        List<? extends Converter.Factory> defaultConverterFactories() {
            return hasJava8Types ? singletonList(OptionalConverterFactory.INSTANCE) : emptyList();
        }
        int defaultConverterFactoriesSize() {
            return hasJava8Types ? 1 : 0;
         }
        ...
    }
    

    我們看到了熟悉的hasJava8Types,這個(gè)就不多說了,如果為true的時(shí)候會(huì)添加一個(gè)這個(gè)工廠,同時(shí)返回的defaultConverterFactoriesSize會(huì)等于1,和上一段代碼相呼應(yīng)。

  5. 在一切都準(zhǔn)備就緒后,一個(gè)Retrofit實(shí)例就成功創(chuàng)建出來了

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

    上面代碼中的unmodifiableList,其實(shí)是Collections.unmodifiableList()這個(gè)方法的大概意思就是,你不能這樣去添加一個(gè)factory工廠:Retrofit.getConverterFactories().add(......),如果這么做就會(huì)報(bào)錯(cuò)。這樣寫的意圖是為了代碼的健壯性。

前菜結(jié)束,下面來幾個(gè)正餐

Retrofit.create()方法究竟做了什么


直接上代碼

public <T> T create(final Class<T> service) {
    validateServiceInterface(service);
    return (T)
        Proxy.newProxyInstance(
            service.getClassLoader(),
            new Class<?>[] {service},
            new InvocationHandler() {
              private final Platform platform = Platform.get();
              private final Object[] emptyArgs = new Object[0];

              @Override
              public @Nullable 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);
                }
                args = args != null ? args : emptyArgs;
                return platform.isDefaultMethod(method)
                    ? platform.invokeDefaultMethod(method, service, proxy, args)
                    : loadServiceMethod(method).invoke(args);
              }
            });
  }

唉咦!!Proxy.newProxyInstance,乍一看仿佛又看到了熟悉的東西,仔細(xì)一看,還確實(shí)是動(dòng)態(tài)代理,代理就是將某個(gè)對象的一些方法交給第二個(gè)對象(代理對象)去完成。舉一個(gè)很形象的例子。

特能謅公司產(chǎn)了型號(hào)為never-stop-740的電瓶車(以下簡寫740電瓶車),這款740電瓶車根本剎不住車,N女士當(dāng)時(shí)不知道有問題,買回來后出了事情,去特能謅公司討要說法,但是無果,這時(shí)候N女士需要一個(gè)更加強(qiáng)大的人來代替她去要說法。
于是她就委托X律師全權(quán)處理剎車失靈的事情。X律師一開始也和N女士一樣去特能謅先去討要說法,但是無果,這個(gè)時(shí)候X律師就想辦法要到了740電瓶車的出廠清單,然后找專業(yè)人士去分析這個(gè)清單,最后實(shí)錘740電瓶車確實(shí)是因?yàn)榧夹g(shù)問題導(dǎo)致剎車失靈,然后X律師拿著740電瓶車剎車失靈的清單報(bào)告將特能謅公司告上了法庭,在充足的證據(jù)面前特能謅不得不對N女士進(jìn)行了道歉,X律師完成了N女士的討回公道的請求。

我們看看N女士的整個(gè)過程,首先N女士有一個(gè)“討回公道”的要求,但是因?yàn)樘啬苤a比較能謅,顯然N女士自己不能完成,于是她就找了代理X律師,X律師代理后首先也是去特能謅討說法(和N女士一樣),但是X律師的手段比N女士多得多,又是聯(lián)系廠商出報(bào)告,又是找專業(yè)人士分析報(bào)告,又是將特能謅告上法庭,最終完成了N女士“討回公道”的需要。

從上面的例子中可以看出代理的作用就是將原來實(shí)體可以實(shí)現(xiàn)的給實(shí)現(xiàn)掉,甚至還能把原來實(shí)體的功能進(jìn)行增強(qiáng),從代碼中看

public interface GitHub {
        @GET("/repos/{owner}/{repo}/contributors")
        Call<List<Contributor>> contributors(@Path("owner") String owner, @Path("repo") String repo);
    }

這里的GitHub類可以看成是N女士,她有一個(gè)訴求就是執(zhí)行contributors方法,獲取到git的倉庫列表。顯而易見,你GitHub只不過是一個(gè)小小接口,啥都干不了,你還想去通過網(wǎng)絡(luò)請求去獲取git倉庫列表?真是小小接口,可笑可笑。就像是N女士面對特能謅討說法束手無策一樣。但是這時(shí)候GitHub接口去找到了動(dòng)態(tài)代理Proxy.newProxyInstance(...),這個(gè)動(dòng)態(tài)代理可以看成是X律師,這個(gè)動(dòng)態(tài)代理可以把GitHub接口中配置的東西(@Get()中的api,contributors方法中的各種請求需要的參數(shù))全部轉(zhuǎn)化為okhttp需要的參數(shù),然后順便再將請求通過okhttp發(fā)送出去,甚至當(dāng)數(shù)據(jù)返回時(shí)還能幫忙把數(shù)據(jù)解析成想要的格式。這真是“山重水復(fù)疑無路,柳暗花明又一村”啊。

那為什么要選擇動(dòng)態(tài)代理呢,如果是選擇靜態(tài)代理,那GitHub有多少種方法,在靜態(tài)代理中就要增加多少個(gè)對應(yīng)的方法。動(dòng)態(tài)代理采用了反射機(jī)制,將所有的請求全部都流經(jīng)這個(gè)動(dòng)態(tài)代理的invoke()方法中,對于使用者來說如果你將來想要往里面添加請求,比如獲取某個(gè)列表的詳情,那只要像contributors方法一樣添加一個(gè)聲明類的方法即可,動(dòng)態(tài)代理會(huì)幫你處理剩下的事情。對,沒錯(cuò),是耗性能,但是retrofit用了這么久,它不香嗎?

接下來我們看看這個(gè)動(dòng)態(tài)代理究竟幫助我們做了哪些重要的事情

首先要明確一個(gè)重要的概念

GitHub github = retrofit.create(GitHub.class);

上述代碼執(zhí)行完后其實(shí)只是創(chuàng)建了一個(gè)代理,下述代碼中的InvocationHandler.invoke方法并不會(huì)馬上被執(zhí)行

public <T> T create(final Class<T> service) {
    validateServiceInterface(service);
    return (T)
        Proxy.newProxyInstance(
            service.getClassLoader(),
            new Class<?>[] {service},
            new InvocationHandler() {
              private final Platform platform = Platform.get();
              private final Object[] emptyArgs = new Object[0];

              @Override
              public @Nullable 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);
                }
                args = args != null ? args : emptyArgs;
                return platform.isDefaultMethod(method)
                    ? platform.invokeDefaultMethod(method, service, proxy, args)
                    : loadServiceMethod(method).invoke(args);//代碼30
              }
            });
  }

那什么時(shí)候被執(zhí)行?就是執(zhí)行下述代碼的時(shí)候

Call<List<Contributor>> call = github.contributors("square", "retrofit");

為什么呢?當(dāng)GitHub github = retrofit.create(GitHub.class);這個(gè)代碼執(zhí)行后,實(shí)際上github 這個(gè)類已經(jīng)不是它自己了,而是一個(gè)代理(X律師)。那代理總歸是能代替原來的實(shí)體做事情的,它做的事情都會(huì)流經(jīng)invoke。那原來的實(shí)體要做什么呢,就是執(zhí)行contributors()方法。動(dòng)態(tài)代理中的原理也需要深入源碼去分析,現(xiàn)在只要知道只有在代理執(zhí)行方法的時(shí)候才會(huì)執(zhí)行invoke方法就行,以后會(huì)出一個(gè)動(dòng)態(tài)代理源碼分析的記錄。而invoke()方法中的method,就相當(dāng)于contributors()這個(gè)方法

明確了這一點(diǎn)后我們看看github(代理).contributors方法會(huì)執(zhí)行哪些東西:

  • private final Platform platform = Platform.get(); 獲取當(dāng)前平臺(tái)

  • return platform.isDefaultMethod(method)
                        ? platform.invokeDefaultMethod(method, service, proxy, args)
                        : loadServiceMethod(method).invoke(args);
    

    執(zhí)行方法

    其中這里首先會(huì)判斷下當(dāng)前需要執(zhí)行的方法是不是默認(rèn)方法,我們跟進(jìn)去看一眼

    boolean isDefaultMethod(Method method) {
        return hasJava8Types && method.isDefault();
    }
    

    hasJava8Types我們先不管,因?yàn)樗黷rue和false都有可能。跟進(jìn)method.isDefault()方法

    /**
     * Returns {@code true} if this method is a default
     * method; returns {@code false} otherwise.
     *
     * A default method is a public non-abstract instance method, that
     * is, a non-static method with a body, declared in an interface
     * type.
     *
     * @return true if and only if this method is a default
     * method as defined by the Java Language Specification.
     * @since 1.8
     */
     public boolean isDefault() {
         // Android-changed: isDefault() implemented using Executable.
         return super.isDefaultMethodInternal();
     }
    

    看注釋,這又是一個(gè)java8的新特性,意思是如果被default修飾符修飾那就返回true,否則返回false。這里再多一嘴這個(gè)新特性

    通常我們寫接口類的方法時(shí)一般只能寫它的類似聲明的一個(gè)方法,而不能寫具體的實(shí)現(xiàn),但是java8中你一旦加入了這個(gè)default修飾符后,你就可以去寫具體的實(shí)現(xiàn)。就像這樣

    interface MyInterface {
        default void eat() {
            System.out.println("I eat beef");
        }
    }
    

    意思是如果有個(gè)類你implement這個(gè)接口類,那你不去實(shí)現(xiàn)這個(gè)eat()方法,那我就調(diào)用默認(rèn)的 System.out.println("I eat beef");

    顯然一般來說我們不可能多去寫這么個(gè)東西,所以method.isDefault()肯定返回false,從而platform.isDefaultMethod(method) 這個(gè)肯定返回false,從而肯定會(huì)執(zhí)行l(wèi)oadServiceMethod(method).invoke(args)這個(gè)方法,這個(gè)方法分兩步走

    第一步:loadServiceMethod(method),我們跟進(jìn)去看看

    public final class Retrofit {
        private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();  
            ...
        ServiceMethod<?> loadServiceMethod(Method method) {
            ServiceMethod<?> result = serviceMethodCache.get(method);//代碼1
            if (result != null) return result;
    
            synchronized (serviceMethodCache) {
              result = serviceMethodCache.get(method);
              if (result == null) {
                result = ServiceMethod.parseAnnotations(this, method);//代碼2
                serviceMethodCache.put(method, result);
              }
            }
            return result;
          }
            ...
    }
    

    這個(gè)方法中代碼1首先從serviceMethodCache這個(gè)map中找method對應(yīng)的ServiceMethod,如果沒有就走代碼2新建一個(gè),然后通過key = method,value = ServiceMethod的方式將ServiceMethod存入map中。為啥要這樣干,很顯然,這是為了性能,ServiceMethod.parseAnnotations方法中存在了大量的反射,反射本身是很耗性能的,我們的ServiceMethod可謂得之不易,非常珍貴,這么珍貴的資源當(dāng)然得存起來,萬一下次再用,我就不用重新再次拼命反射獲得了。再深入一下,看看ServiceMethod.parseAnnotations究竟是干嘛的

    abstract class ServiceMethod<T> {
      static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
        RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
          ...
        return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
      }
    
      ...
    }
    

    從上述代碼看出這里會(huì)做兩件事情RequestFactory.parseAnnotations(retrofit, method);return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);,接下來我們展開講講這兩個(gè)方法

RequestFactory.parseAnnotations(retrofit, method)方法究竟做了什么


看下面的代碼

final class RequestFactory {
  static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    return new Builder(retrofit, method).build();
  }
    ...
  RequestFactory build() {
      for (Annotation annotation : methodAnnotations) {//代碼1
        parseMethodAnnotation(annotation);//代碼3
      }
        ...

      int parameterCount = parameterAnnotationsArray.length;//代碼4
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
        parameterHandlers[p] =
            parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
      }
        ...

      return new RequestFactory(this);//代碼6
    }
    ...
}
...
  static final class Builder {
      ...
      final Annotation[] methodAnnotations;
      final Annotation[][] parameterAnnotationsArray;
      ...
      Builder(Retrofit retrofit, Method method) {
            ...
          this.methodAnnotations = method.getAnnotations();//代碼2:獲取方法上的注解
          this.parameterAnnotationsArray = method.getParameterAnnotations();//代碼5:獲取方法中參數(shù)的注解
            ...
    }
  }

調(diào)用了parseAnnotations方法后,會(huì)直接調(diào)用build()方法,這個(gè)build方法首先會(huì)執(zhí)行代碼1這個(gè)循環(huán)的作用就是取出方法上的所有注解以及內(nèi)容(代碼2中展示了怎么獲取方法上的注解),然后進(jìn)行一個(gè)url的字符拼接和確定是post/get/put/...的請求。具體的方法就在代碼3中,我們跟進(jìn)去看看

private void parseMethodAnnotation(Annotation annotation) {
    //設(shè)置是什么類型的請求
      if (annotation instanceof DELETE) {
        parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);//代碼4
      } else if (annotation instanceof GET) {
        parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
      }
        ...
     //設(shè)置頭部
        else if (annotation instanceof retrofit2.http.Headers) {
        String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
        if (headersToParse.length == 0) {
          throw methodError(method, "@Headers annotation is empty.");
        }
        headers = parseHeaders(headersToParse);
      } 
        ...
    }

其中代碼4中的第二個(gè)參數(shù)取的就是url后面的東西,比如我的樣例中請求方法的頭部是這樣的@GET("/repos/{owner}/{repo}/contributors") 那取的就是括號(hào)中的字符,具體怎么解析的,我們看代碼

    private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
      if (this.httpMethod != null) {
        throw methodError(
            method,
            "Only one HTTP method is allowed. Found: %s and %s.",
            this.httpMethod,
            httpMethod);
      }
      this.httpMethod = httpMethod;
      this.hasBody = hasBody;

      if (value.isEmpty()) {
        return;
      }

      // Get the relative URL path and existing query string, if present.
      int question = value.indexOf('?');
      if (question != -1 && question < value.length() - 1) {
        // Ensure the query string does not have any named parameters.
        String queryParams = value.substring(question + 1);
          //這里是大括號(hào)的正則
        Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);

      this.relativeUrl = value;
          //這里是將所有的大括號(hào)中的內(nèi)容根據(jù)正則取出賦值給relativeUrlParamNames
      this.relativeUrlParamNames = parsePathParameters(value);
    }

簡單來說,就是保存當(dāng)前是什么類型的請求,然后請求中的?后面的內(nèi)容取出來,還有就是替換掉{XXX}中包含的東西并保存好。

代碼4開始,就是獲取方法中參數(shù)的注解并保存到ParameterHandler<?>[] parameterHandlers中,我們可以看到,在代碼5中實(shí)際上是用了二維數(shù)組來保存方法中參數(shù)的注解的,這是因?yàn)椋椒ㄖ械膮?shù)注解可以有多個(gè)比如這個(gè)樣子

Call<List<Contributor>> contributors(@Field ("ss")@Path("owner") String owner)

所以parameterAnnotationsArray的含義是parameterAnnotationsArray[參數(shù)][注解],參數(shù)可以有很多個(gè),每個(gè)參數(shù)中對應(yīng)的注解也可以有很多個(gè)

最后執(zhí)行代碼6返回,接下來分析HttpServiceMethod.parseAnnotations

HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)方法究竟做了什么


總體來說這個(gè)方法就是做了兩件事

  • 選擇合適此次請求的CallAdapter
  • 選擇合適此次請求的Converter

為什么是“合適此次請求”?很簡單,我們構(gòu)建Retrofit的時(shí)候肯定可以這樣干

new Retrofit.Builder()
                        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                        .addCallAdapterFactory(RxJava2CallAdapterFactoryB.create())
                        .addCallAdapterFactory(RxJava2CallAdapterFactoryC.create())
                        .addConverterFactory(GsonConverterFactory.create())
                        .addConverterFactory(GsonConverterFactoryB.create())
                        .addConverterFactory(GsonConverterFactoryC.create())

那你搞出這么多的CallAdapter和Converter的工廠,真正在請求的時(shí)候,Retrofit肯定只會(huì)用到一個(gè)啊,那不得通過返回值來篩選一下子啊,聽懂掌聲——暗示點(diǎn)贊

具體我們跟進(jìn)代碼中看看

  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
    boolean continuationWantsResponse = false;
    boolean continuationBodyNullable = false;

    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
    if (isKotlinSuspendFunction) {//代碼7
        ...
    } else {
      adapterType = method.getGenericReturnType();//代碼8
    }

    CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);//代碼10
    Type responseType = callAdapter.responseType();
      ...
    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);//代碼11

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    if (!isKotlinSuspendFunction) {
      return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);//代碼9
    } else if (continuationWantsResponse) {
      ...
    } else {
       ...
    }
  }

首先要明確一點(diǎn),HttpServiceMethod是繼承ServiceMethod的,然后我們往里面看看。

首先看到代碼7這是一個(gè)判斷是否為kotlin的Suspend關(guān)鍵字的掛起方法,顯然不是,所以執(zhí)行到了代碼8這個(gè)代碼的意思是獲取請求網(wǎng)絡(luò)方法的返回值,想想也對,我們要確認(rèn)是哪個(gè)CallAdapter或者Convert那不得從返回值的類型入手嘛。

接下來執(zhí)行到了代碼10,這段代碼就是幫我們選擇合適的CallAdapter的,究竟是怎么篩選的呢,來來來我們深入了解下

abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
    ...
    private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
      Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
    try {
      //noinspection unchecked
      return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);//代碼12
    } catch (RuntimeException e) { // Wide exception range because factories are user code.
      throw methodError(method, e, "Unable to create call adapter for %s", returnType);
    }
  }
    ...
}
public final class Retrofit {
    ...
    public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);//代碼13
  }
  public CallAdapter<?, ?> nextCallAdapter(
      @Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {//代碼15
    ...
    int start = callAdapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);//代碼14
      if (adapter != null) {
        return adapter;
      }
    }
    ...
}

如上述代碼,首先我們的代碼10執(zhí)行后會(huì)有一系列的跳轉(zhuǎn):代碼10->代碼12->代碼13->代碼15,直接看代碼15代碼15中有一個(gè)skipPast的參數(shù)是告訴程序,你不用給我找從第一個(gè)CallAdapter.Factory到skipPast之間的所有CallAdapter.Factory了,你給我直接從skipPast后面開始for循環(huán)。顯然代碼13傳的是null,所以暫時(shí)不用管,想要繼續(xù)擴(kuò)展的可以看下SkipCallbackExecutor這個(gè)注解。

代碼15以后是一個(gè)for循環(huán),這個(gè)循環(huán)的作用是找出符合條件的CallAdapter,其中最主要的代碼是代碼14,如果循環(huán)過程中代碼14返回的不為null,就說明已經(jīng)找到合適的了,并直接返回結(jié)果,我們進(jìn)去代碼14get(returnType, annotations, this)方法中一探究竟

abstract class Factory {
    /**
     * Returns a call adapter for interface methods that return {@code returnType}, or null if it
     * cannot be handled by this factory.
     */
    public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit);//代碼16
    ...
}
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
    ...
  @Override
  public @Nullable CallAdapter<?, ?> get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
    final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);

    final Executor executor =//代碼17
        Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
            ? null
            : callbackExecutor;

    return new CallAdapter<Object, Call<?>>() {//代碼18
      @Override
      public Type responseType() {
        return responseType;
      }

      @Override
      public Call<Object> adapt(Call<Object> call) {
        return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
      }
    };
  }
    ...
}

執(zhí)行到代碼16的時(shí)候就會(huì)代碼14中對應(yīng)取到的CallAdapter.Factory來執(zhí)行g(shù)et()方法,就拿DefaultCallAdapterFactory來舉個(gè)例子,代碼17中其實(shí)就是判斷當(dāng)前是否需要跳過,如果是跳過就給Executor = null如果不要跳過那就給他原來賦值的callbackExecutor,這個(gè)callbackExecutor之前講過,安卓平臺(tái)默認(rèn)就是切換線程用的,代碼18中就返回了一個(gè)CallAdapter,到此代碼10就這樣分析完畢

接下來我們看看代碼11,這段代碼其實(shí)就是幫我們篩選出符合條件的Converter的,老規(guī)矩,進(jìn)去繼續(xù)深入聊聊

abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
    ...
    private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(
      Retrofit retrofit, Method method, Type responseType) {
        Annotation[] annotations = method.getAnnotations();
        try {
          return retrofit.responseBodyConverter(responseType, annotations);//代碼19
        } catch (RuntimeException e) { // Wide exception range because factories are user code.
          throw methodError(method, e, "Unable to create converter for %s", responseType);
        }
  }
   ...
    
}
public final class Retrofit {
    ...
    public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
        return nextResponseBodyConverter(null, type, annotations);//代碼20
    }
    
    
    public <T> Converter<ResponseBody, T> nextResponseBodyConverter(//代碼23
      @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
        Objects.requireNonNull(type, "type == null");
        Objects.requireNonNull(annotations, "annotations == null");

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

上述代碼可以看到,過濾Converter和過濾CallAdapter的套路大同小異,我們看看代碼流向:代碼19->代碼20->代碼23

前面幾個(gè)代碼流向就不多說了,直接看代碼21,這里也是過濾掉了帶有SkipCallbackExecutor的Converter,然后不斷循環(huán)之前配的converterFactories,看代碼22循環(huán)體中會(huì)調(diào)用responseBodyConverter()方法,如果返回不為null就表示找到了合適的Converter,進(jìn)入responseBodyConverter方法康康

  abstract class Factory {
    public @Nullable Converter<ResponseBody, ?> responseBodyConverter(
        Type type, Annotation[] annotations, Retrofit retrofit) {
      return null;
    }
  }

返回null,很明顯是通過子類來實(shí)現(xiàn)的,以GsonConverterFactory為例

public final class GsonConverterFactory extends Converter.Factory {
      @Override
      public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
          Retrofit retrofit) {
        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        return new GsonResponseBodyConverter<>(gson, adapter);
      }
    ...
}
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
  private final Gson gson;
  private final TypeAdapter<T> adapter;

  GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
    this.gson = gson;
    this.adapter = adapter;
  }

  @Override public T convert(ResponseBody value) throws IOException {
    JsonReader jsonReader = gson.newJsonReader(value.charStream());
    try {
      return adapter.read(jsonReader);
    } finally {
      value.close();
    }
  }
}

看上述代碼其實(shí)就是把返回的值轉(zhuǎn)化為json格式,這邊就貼兩段代碼,具體也沒啥好講的,實(shí)在有不明白的可以在評(píng)論區(qū)留個(gè)言。

最后我們再看一眼代碼9,這段代碼把剛才篩選出的CallAdater和Converter作為參數(shù)給了CallAdapted的構(gòu)造函數(shù)生成了一個(gè)新的CallAdapted實(shí)體,注意:是CallAdapted 不是CallAdater,CallAdated是最終形態(tài),他是繼承HttpServiceMethod的。

static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT>

到這里為止所有的東西已經(jīng)就緒,現(xiàn)在就差調(diào)用okhttp,接下來會(huì)詳細(xì)講解Retrofit是如何調(diào)用okhttp的

生成Call


我們的樣例代碼中有這么一行

Call<List<Contributor>> call = github.contributors("square", "retrofit");

那這個(gè)call是怎么來的?嘿嘿,不要忘了,我們分析到現(xiàn)在還只是分析了動(dòng)態(tài)代理中invoke方法中的loadServiceMethod(method)返回值是怎么來的,那返回值后面還低調(diào)地寫了一個(gè)方法:.invoke(args),低調(diào)但是也不平凡,這個(gè)方法直接返回了Call,且聽我娓娓道來。

老規(guī)矩,跟代碼

abstract class ServiceMethod<T> {
    ...
    abstract @Nullable T invoke(Object[] args);//代碼24
}
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
    ...
    @Override
    final @Nullable ReturnT invoke(Object[] args) {
        Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
        return adapt(call, args);//代碼25
    }
    protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);//代碼26
    ...
}
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
    private final CallAdapter<ResponseT, ReturnT> callAdapter;
    ...
    @Override
    protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
      return callAdapter.adapt(call);//代碼27
    }
  }
public interface CallAdapter<R, T> {
    ...
      T adapt(Call<R> call);//代碼28
    ...
}

代碼流向是這樣:代碼24->代碼25->代碼26->代碼27->代碼28,到代碼28是不是發(fā)現(xiàn)走不下去了?那就對了,你看看28是在哪個(gè)類下?CallAdapter,是不是很熟悉?沒錯(cuò)這個(gè)就是之前被我們循環(huán)篩選,選出來的工廠造出來地CallAdapter,你回去看一眼代碼18,代碼27執(zhí)行后必然會(huì)執(zhí)行下面的代碼(代碼18匿名類中的方法)

 @Override
public Call<Object> adapt(Call<Object> call) {
    return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
}

那么這個(gè)executor是什么?當(dāng)然是Android(extends Platform)平臺(tái)的類中的MainThreadExecutor啦,當(dāng)然不可能為null啦,所以肯定會(huì)是新建一個(gè)ExecutorCallbackCall實(shí)例,下面是這個(gè)類的代碼

static final class ExecutorCallbackCall<T> implements Call<T> {
    final Executor callbackExecutor;
    final Call<T> delegate;

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

    @Override
    public void enqueue(final Callback<T> callback) {
      Objects.requireNonNull(callback, "callback == null");

      delegate.enqueue(
          new Callback<T>() {
            @Override
            public void onResponse(Call<T> call, final Response<T> response) {
              callbackExecutor.execute(
                  () -> {
                    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(() -> callback.onFailure(ExecutorCallbackCall.this, t));
            }
          });
    }

    @Override
    public boolean isExecuted() {
      return delegate.isExecuted();
    }

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

    @Override
    public void cancel() {
      delegate.cancel();
    }

    @Override
    public boolean isCanceled() {
      return delegate.isCanceled();
    }

    @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
    @Override
    public Call<T> clone() {
      return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
    }

    @Override
    public Request request() {
      return delegate.request();
    }

    @Override
    public Timeout timeout() {
      return delegate.timeout();
    }
  }

如果你曾經(jīng)使用過okhttp,可以在這里看到,幾個(gè)熟悉的方法enqueue,execute,timeout...我的天,retrofit居然把okhttp中的Call又自己做了一層封裝:retrofit2.Call !!!

Retrofit:okhttp老兄,有人說你不好用,連個(gè)線程切換都沒有,還要人去哼哧哼哧地封裝,你早晚讓人給斃了

okhttp(驚恐臉):那怎么辦,老弟你可得給我支支招啊

Retrofit:也不是不行,你跟我合作,我可是出了名地好用,到時(shí)候把你封裝進(jìn)來,用的人就多了啊

okhttp(長嘆一口氣):多謝老弟,老弟費(fèi)心,來根煙

okhttp彎下腰遞了一根煙給Retrofit

Retrofit(陰險(xiǎn)內(nèi)心獨(dú)白):我調(diào)你用我自己封裝的Call,讓程序員用我的時(shí)候完全感知不到你的存在,我看幾年后誰還記得你,咩,哈哈哈哈~

這究竟是道德的淪陷還是。。。

其實(shí)是因?yàn)镽etrofit設(shè)計(jì)初衷就是想靈活適配網(wǎng)絡(luò)請求框架的,這樣做的話可以體現(xiàn)出我是獨(dú)立的,你們?nèi)魏稳硕伎梢院臀液献鳎灰龊苌俚倪m配。

只不過目前為止還是只適配了okhttp。。。

現(xiàn)在Call已經(jīng)生成了,我們接著樣例代碼往下走

List<Contributor> contributors = call.execute().body();

執(zhí)行網(wǎng)絡(luò)請求

當(dāng)執(zhí)行了call.execute()后就直接執(zhí)行到了代碼29,在這個(gè)方法中發(fā)現(xiàn)它執(zhí)行的是delegate.execute();我們猜測,這個(gè)delegate其實(shí)就是okhttp的call,證據(jù)如下

首先我們再回到夢開始的地方——代理執(zhí)行invoke方法的地方見代碼30

進(jìn)入invoke方法,我們再看這里面有個(gè)啥

 @Override
  final @Nullable ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);//代碼31
    return adapt(call, args);
  }

所有的請求都會(huì)走這個(gè)invoke。我們看看代碼31,這段代碼返回的東西,就是我們之前分析的retrofit2.Call,如果能證明OkHttpCall里面的execute方法確實(shí)調(diào)用了Okhttp3.Call.execute()方法,那整個(gè)流程就通了。看代碼

final class OkHttpCall<T> implements Call<T> {
    @Override
    public Response<T> execute() throws IOException {
        okhttp3.Call call;//代碼32

        synchronized (this) {
          if (executed) throw new IllegalStateException("Already executed.");
          executed = true;

          call = getRawCall();//代碼33
        }

        if (canceled) {
          call.cancel();
        }

        return parseResponse(call.execute());
  }
    ...
    @GuardedBy("this")
    private okhttp3.Call getRawCall() throws IOException {//代碼34
        okhttp3.Call call = rawCall;//代碼35
        if (call != null) return call;
        ...
              // Create and remember either the success or the failure.
        try {
          return rawCall = createRawCall();//代碼36
        } catch (RuntimeException | Error | IOException e) {
          throwIfFatal(e); // Do not assign a fatal error to creationFailure.
          creationFailure = e;
          throw e;
        }
        }
    
    ...
    private okhttp3.Call createRawCall() throws IOException {
        okhttp3.Call call = callFactory.newCall(requestFactory.create(args));//代碼37
        if (call == null) {
          throw new NullPointerException("Call.Factory returned null.");
        }
        return call;
    }

}

代碼流向:代碼33->代碼34->代碼35 ->代碼36->代碼37,還記得callFactory的賦值嗎?對的,就是如果在build構(gòu)建Retrofit時(shí)沒有賦值,那就默認(rèn)OkhttpClient,下面的代碼幫助回憶一下:

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

證畢,結(jié)果:實(shí)錘retrofit2.Call == okhttp3.Call

接下來執(zhí)行execute方法其實(shí)就是okhttp3.Call.execute(),我之前寫了一篇文章是以okhttp3.Call.equeue()為例的,其實(shí)原理都差不多,有興趣的可以看一下我的文章:okhttp3原理解析——概覽(非常概括)

結(jié)語


頭一回寫這么長篇的源碼解析,寫到這里其實(shí)也漲了不少的知識(shí),閱讀源碼確實(shí)是一個(gè)很好的習(xí)慣,都說閱讀書本是在和圣賢交流,交流多了就能成為圣賢。那閱讀優(yōu)秀源碼其實(shí)也是在和大神交流,交流多了不說能成為大神,至少對以后的學(xué)習(xí)和能力的提升都是一筆不小的財(cái)富。Retrofit確實(shí)是一個(gè)很優(yōu)秀的開源框架,我也是看了3天才大致了解里面的工作流程,好的東西真的是每次看都能發(fā)現(xiàn)新的知識(shí),每次都能將自己的認(rèn)知升那么一小段。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評(píng)論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,538評(píng)論 3 417
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評(píng)論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評(píng)論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,761評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,207評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,419評(píng)論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,959評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,782評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,983評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,222評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評(píng)論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,678評(píng)論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,978評(píng)論 2 374

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

  • Retrofit2作為目前最火的網(wǎng)絡(luò)請求框架之一,它是一個(gè)由Square組織開發(fā)的可以在Android和java中...
    maoqitian閱讀 671評(píng)論 0 1
  • 一、什么是Retrofit A type-safe HTTP client for Android and Jav...
    andcoder閱讀 782評(píng)論 2 3
  • 適配器模式上一篇文章我們已經(jīng)分析了Retrofit解析注解封裝進(jìn)ServiceMethod的流程,讀者在這里要記住...
    andcoder閱讀 669評(píng)論 0 2
  • 如果你還沒了解Retrofit如何使用,可以先查看這篇文章:Retrofit使用指南 一般分析源碼都習(xí)慣從使用開始...
    一只小雞仔閱讀 738評(píng)論 1 4
  • 前言 為什么要看Retrofit源碼?因?yàn)槟壳绊?xiàng)目使用的Retrofit網(wǎng)絡(luò)請求。想去詳細(xì)了解下。 這次閱讀重點(diǎn)關(guān)...
    崔鵬宇閱讀 426評(píng)論 0 1