Retrofit的框架結(jié)構(gòu)是什么?底層是怎么實現(xiàn)的?

美圖.jpg

Retrofit簡單介紹:

retrofit是什么?

  • Retrofit是針對于Android/Java的、基于okHttp的、一種輕量級且安全的、并使用注解的網(wǎng)絡(luò)請求框架。
  • 它有哪些優(yōu)勢?

首先,Retrofit使用注解方式,簡化了我們的URL拼寫形式,而且注解含義一目了然,簡單易懂;
其次,Retrofit使用簡單,結(jié)構(gòu)層次分明,每一步都能清晰的表達出之所以要使用的寓意;
再者,Retrofit支持同步和異步執(zhí)行,使得請求變得簡單,只要調(diào)用enqueue/execute即可完成;
最后,Retrofit更大自由度的支持我們自定義的業(yè)務(wù)邏輯,如自定義Converters。

  • retrofit的原理:

Retrofit使用接口+注解的形式來定義一個網(wǎng)絡(luò)請求,現(xiàn)在有很多開源框架使用了注解,如Dagger2、ButterKnife等,以及Retrofit。所不同的是他們利用注解干的事卻不一樣。 Dagger2、ButterKnife他們在編譯期間就處理注解生成代碼,提供依賴注入(依賴注入和控制反轉(zhuǎn)有時間再寫)。Retrofit則是在運行期間處理注解,通過動態(tài)代理的方式來提供AOP(面向切面)能力。
下面從Retrofit以下幾個方面來分析:
(1)建造者模式
(2)代理模式
(3)注解

  • 至于HttpClient、HttpConnection、okhttp、retrofit之間聯(lián)系和區(qū)別不再展開,本文更傾向是分析retrofit的原理和源碼探索。

Retrofit的源碼簡單分析

(1)建造者模式-------創(chuàng)建Retrofit實例

//使用建造者模式創(chuàng)建Retrofit實例
    Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.oschina.net/action/apiv2/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
//創(chuàng)建Github接口對象
    NetApi netApi = retrofit.create(NetApi.class);
    Call<NewListBean> newList = netApi.getNewList(0, 1, 10);
//NetApi接口的定義
    public interface NetApi {
        @GET("news_list")
        public Call<NewListBean> getNewList(@Query("pageIndex") int pageIndex,@Query("catalog") int catalog,@Query("pageSize") int pageSize);
}
//執(zhí)行異步請求
    newList.enqueue(new Callback<NewListBean>() {
                @Override
                public void onResponse(Call<NewListBean> call, Response<NewListBean> response) {
                    System.out.println(response.body().obj_list.get(0).author.name);
                }

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

這里最重要的代碼就是下面這個段,使用的是建造者模式,應(yīng)該很多人都熟悉

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.oschina.net/action/apiv2/")
                .addConverterFactory(GsonConverterFactory.create())
                .build(); 

源碼如下

    //1、new Rtrofit.Builder()走的就是這個構(gòu)造,Builder為Retrofit的靜態(tài)內(nèi)部類
    public Builder() {
      this(Platform.get());
    }
    
    //2、上一段代碼調(diào)用
    Builder(Platform platform) {
      this.platform = platform;
      converterFactories.add(new BuiltInConverters());
    }
    
    //3、調(diào)用.baseUrl的時候調(diào)用,返回的是Builder,建造者模式
    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;
    }
    
    //4、調(diào)用.build()的時候調(diào)用,返回的是retrofit實例
    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);
      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);
    }

(2)動態(tài)代理模式-------創(chuàng)建接口實例(代理對象)

傳入我們寫的接口的class對象,返回接口的代理對象

    NetApi netApi = retrofit.create(NetApi.class);

源碼如下:

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

大家可以看到返回的是

Proxy.newProxyInstance(...);

retrofit.create()方法返回了一個動態(tài)代理對象。Java動態(tài)代理就是每當(dāng)我們調(diào)用代理類里面的方法時,invoke()都會被執(zhí)行,我們就可以在invoke()插入想要執(zhí)行的代碼,并且我們可以從該方法的參數(shù)中獲取到所需要的一切信息,比如從method中獲取到方法名,從args中獲取到方法名中的參數(shù)信息等,這個就是Java的動態(tài)代理。大家可以看到Proxy.newProxyInstance(...)方法的最后一個參數(shù)就是InvocationHandler,InvocationHandler有一個方法是invoke,當(dāng)我們執(zhí)行Call<NewListBean> newList = netApi.getNewList(0, 1, 10);這段代碼的時候,返回的Proxy.newProxyInstance(...)返回的代理對象,并不是NetApi的實現(xiàn)類對象,當(dāng)我們調(diào)用netApi.getNewList(0,1,10)方法時,動態(tài)代理機制就會調(diào)用上面InvocationHandler的invoke()方法,從而我們通過代理機制在invoke()來插入我們想要加入的代碼,比如我拿我女朋友的錢包去買菜,錢包就是實際對象,我就是代理對象,我在買菜的時候需要先判斷錢包的錢夠不夠,并且我在買菜的時候才動態(tài)去判斷,這個判斷只有在買菜的時候才去判斷。這個判斷的過程就是類似invoke方法,只有方法運行的時候才被調(diào)用。點到為止,有時間專門寫一篇動態(tài)代理的。
ServiceMethod serviceMethod = loadServiceMethod(method)。。。待更新

(3)java注解-------解析(代理對象)

待更新。。。。。。。

參考文章:
Retrofit簡單原理分析
http://blog.csdn.net/lyric_315/article/details/52710464
Android 網(wǎng)絡(luò)框架之Retrofit2使用詳解及從源碼中解析原理
http://blog.csdn.net/guiman/article/details/51480497

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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