Retrofit 源碼解析

Retrofit 源碼解析

簡單用法

Retrofit最簡單的用法就是定義一個接口碌嘀,創(chuàng)建Retrofit對象虏冻,調(diào)用create()方法得到一個service,
然后自己根據(jù)service中的方法去做同步或者異步的請求异逐,拿到數(shù)據(jù)對象,十分簡單快速,簡單代碼如下:

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

.創(chuàng)建
Retrofit retrofit = new Retrofit.Builder().baseUrl("xxx").build();
.代理
GitHub gitHub = retrofit.create(GitHub.class);
Call<List<Integer>> call = gitHub.contributors("xx", "xx");
.執(zhí)行
call.enqueue(new Callback<List<Integer>>() {
    @Override
    public void onResponse(Call<List<Integer>> call, Response<List<Integer>> response) {

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

    }
});

流程分析

創(chuàng)建

那這么簡單的過程酝掩,剛開始看的時候覺得有點(diǎn)懵逼呀,怎么他就幫你完成了請求眷柔,你明明什么都沒有做期虾,下面我們按照它的流程慢慢來解析一下整個過程。
我們要用Retrofit,首先自然是要創(chuàng)建它,也就是這行代碼Retrofit retrofit = new Retrofit.Builder().baseUrl("xxx").build();.
這里創(chuàng)建Retrofit是通過它的一個內(nèi)部類Builder來創(chuàng)建的驯嘱,也就是創(chuàng)建者模式镶苞,這個模式很簡單,不知道的自行百度鞠评,谷歌茂蚓。
好,我們來看看這個builder做了什么,除了初始化有個Platform.get(),直接看最后的build(),其余的方法都是設(shè)置參數(shù)剃幌,主要就是這個build()

public Builder() {
      this(Platform.get());
}
public Retrofit build() {
  1.
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
  2.
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }
  3.
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }
  4.
      // 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));
 5.
      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

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

首先一初始化聋涨,就做了一件事情,是啥Platform.get()负乡,Platform是啥牍白?直譯過來就是平臺啊,平臺是啥抖棘?為啥要有平臺淹朋?看下面這個代碼get()其實(shí)
就是一個就是調(diào)用findPlatform()

private static final Platform PLATFORM = findPlatform();

static Platform get() {return PLATFORM;}

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

AndroidJava8兩種平臺,Android我們還是能理解的钉答,為啥還有個Java8础芍,不要問我,我也不知道啊数尿,Retrofit的作者炒雞暖男仑性,關(guān)心全世界各種碼農(nóng),
我是個寫android代碼的我們就看Android平臺就好了
下面我們來看一下build()這個方法:

  • 第一步很簡單右蹦,沒有baseUrl拋出異常诊杆,最基本的沒有,事情沒法干是吧何陆。
  • 第二步晨汹,如果沒有給他設(shè)置callFactory,那默認(rèn)給他一個callFactory贷盲,默認(rèn)就是新創(chuàng)建一個OkHttpClient淘这,這里可能我們會有自己做過一些
    處理的OkHttpClient,比如加了Interceptor啊之類的剥扣,設(shè)置進(jìn)來就好了,就不會用默認(rèn)的铝穷。
    有人可能會問啥是callFactory啊 钠怯?callFactory嘛,就是call的factory嘛曙聂,call是啥晦炊,就是請求,factory是啥宁脊,就是工廠断国,callFactory就是創(chuàng)建請求的
    工廠,OkHttpClient就是一個很牛逼的創(chuàng)建請求的工廠榆苞,不在本文討論范圍內(nèi)稳衬,就不多言了。
  • 第三步语稠,設(shè)置callbackExecutor,又來一個宋彼,這callbackExecutor又是啥呢?callback就是回調(diào)嘛仙畦,啥回調(diào)输涕,就是網(wǎng)絡(luò)請求返回回來數(shù)據(jù)的回調(diào),executor呢慨畸,就是執(zhí)行者
    莱坎,合起來就是回調(diào)的執(zhí)行者,意思網(wǎng)絡(luò)成功了之后交給他它了寸士。如果你沒有設(shè)置它就自己整一個默認(rèn)的回調(diào)嘛檐什,不能沒有。但是這里它要搞事情了弱卡,它返回了一個啥乃正?
    platform.defaultCallbackExecutor();來,我們看一下android下它返回的是啥:
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);
      }
    }
  }

是啥婶博?MainThreadExecutor()啊瓮具,啥意思就是主線程啊,下面寫的明明白白的Looper.getMainLooper()再把要執(zhí)行的Runnablepost到主線程上執(zhí)行
因?yàn)樗悄J(rèn)的嘛凡人,可能就說大多數(shù)人都是得到數(shù)據(jù)更新UI啊啥的名党,所以就默認(rèn)在主線程上執(zhí)行回調(diào)了。我就不想拿到數(shù)據(jù)在主線程座做咋辦挠轴,我拿到數(shù)據(jù)我就想更新數(shù)據(jù)庫传睹,
我想在IO線程上搞事情,那就自己寫個callbackExecutor岸晦,自己在IO線程上做就好了欧啤,人家提供了一個方法callbackExecutor(Executor executor)給你睛藻,你自己設(shè)置進(jìn)去就好了

  • 第四步是啥?看代碼說話堂油,那就是設(shè)置callAdapterFactory啊 修档。callAdapterFactory又是什么鬼啊碧绞,和上面一樣啊府框,拆分一下呀。CallAdapter啥意思讥邻,就是請求的
    適配器迫靖,請求的適配器是什么鬼啊。來來來我告訴你兴使,你看看源碼里面根目錄是不是有一個包名字叫做'retrofit-adapter',這個包就是實(shí)現(xiàn)了一些列的CallAdapter
    意思就是你想將返回的數(shù)據(jù)用什么東西包裝起來系宜,比如你用Rxjava的話想返回Observable,或者高興发魄,想用Java8CompletableFuture盹牧,這些都由你呀。
    但是這些都實(shí)現(xiàn)了一個叫CallAdapter的接口励幼。我們來簡單看看這個接口:
public interface CallAdapter<R, T> {
  Type responseType();
  T adapt(Call<R> call);
  abstract class Factory {
    public abstract CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
        Retrofit retrofit);
    protected static Type getParameterUpperBound(int index, ParameterizedType type) {
      return Utils.getParameterUpperBound(index, type);
    }
    protected static Class<?> getRawType(Type type) {
      return Utils.getRawType(type);
    }
  }
}

其實(shí)接口里面就是兩個方法還有一個靜態(tài)的工廠類汰寓。responseType()這個方法決定請求回來之后返回的是什么類型的數(shù)據(jù)透绩。比如在示例用法中我們的List<Integer>
adapt()這個方法是干嘛的呢励饵?就是適配嘛,就是怎樣把返回回來的數(shù)據(jù)通過這個方法包裝成你想要的對象壹士。
這里看到這個名字adapter你想到了啥嵌削,其實(shí)就是傳說中的適配器模式啊毛好,就是我給你定義一個接口放這里,我在框架里的邏輯就用這個接口來做就好了苛秕,至于你想要怎樣的實(shí)現(xiàn)肌访,
想用框架供給你的一些實(shí)現(xiàn)比如Rxjava或者Java8CallAdapter,或者是你自己心情好想用自己的實(shí)現(xiàn)一個其他的CallAdapter,你自己決定就好了艇劫。這就是傳說中的啥吼驶??擴(kuò)展性好啊港准。
繼續(xù)看build()
這個方法旨剥,它調(diào)用的是adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));· 再回來PlatformdefaultCallAdapterFactory()返回的是一個ExecutorCallAdapterFactory。這個類他么的又來干嘛浅缸,當(dāng)然是搞事情轨帜。 進(jìn)去瞅一眼,發(fā)現(xiàn)了什么衩椒?它當(dāng)然是繼承CallAdapter.Factory了蚌父,這個不說了哮兰,看幾句代碼來,看它的get()方法苟弛,看看這個工廠是怎么造CallAdapter`的:

  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

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

返回了一個簡單新創(chuàng)建的實(shí)現(xiàn)CallAdapter的匿名類喝滞。注意看看這里的adapt()方法,前面講了就是用它來實(shí)現(xiàn)到底返回什么包裝對象的邏輯膏秫。這里返回的是一個
ExecutorCallbackCall,ExecutorCallbackCall是這ExecutorCallAdapterFactory里面的一個內(nèi)部類.來看看它的代碼:

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

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

  @Override public Response<T> execute() throws IOException {
    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();
  }
}

它實(shí)現(xiàn)了Call這個接口右遭,Call我們前面說了,是啥缤削,就是一個請求嘛窘哈,然而我們看這里并沒有實(shí)際做請求而是用了一個靜態(tài)代理,
通過代理類的實(shí)現(xiàn)來實(shí)現(xiàn)call請求亭敢,而在這里面做了一些其他的邏輯比如cancel的邏輯滚婉,而實(shí)際上做請求的還是交個了delegate -> OkHttpCall.

  • 第五步,接著看上面的build()的代碼帅刀,不要著急让腹,第一段代碼還沒講完呢。第五步是什么扣溺?List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
    這一步就是關(guān)于Converter骇窍,顧名思義,它就是一個轉(zhuǎn)換器娇妓,什么轉(zhuǎn)換器像鸡,數(shù)據(jù)的轉(zhuǎn)換器,我們從后端獲取到的數(shù)據(jù)哈恰,一般都是一些序列化的數(shù)據(jù)只估,例如json,xml,protobuf之類的
    而我們前端用到的需要的是一個對象,我們就需要吧這些序列化的數(shù)據(jù)轉(zhuǎn)換成我們想要的能直接用的用起來爽的對象着绷,這時候就需要現(xiàn)在登場的這個東西』赘疲現(xiàn)在json用的
    比較多,我們平時都會用什么gson,jackson或者其他的三方庫來轉(zhuǎn)化它荠医,你覺得哪個用起來高興就可以用什么寫一個Converter,然后用Builder中的addConverterFactory
    就可以用你想要的了吁脱,而且你都不用寫,因?yàn)楣俜教峁┝撕枚喾NConverter的彬向,在根目錄下的'retrofit-converters'這個包下面兼贡,你只需要用就好了,那我們這里如果沒有設(shè)置過converterFactories
    咋辦娃胆?咋辦遍希?沒設(shè)置,后面找不到會報錯的里烦。
    這里的ResponseRetrofitOkHttpResponseBody封裝了一些邏輯的類凿蒜,源碼就不貼了禁谦,自己點(diǎn)進(jìn)去看看。
    這里我們順便看看Converter這個接口:
public interface Converter<F, T> {
  T convert(F value) throws IOException;
  abstract class Factory {
    
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
        Retrofit retrofit) {
      return null;
    }
    public Converter<?, RequestBody> requestBodyConverter(Type type,
        Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
      return null;
    }
    public Converter<?, String> stringConverter(Type type, Annotation[] annotations,
        Retrofit retrofit) {
      return null;
    }
  }
}

接口就一個方法废封,就是轉(zhuǎn)換州泊,然后里面還有一個靜態(tài)的工廠類我們看到里面有3個方法,其實(shí)很好理解漂洋。我們需要把返回來的ResponseBody里的數(shù)據(jù)轉(zhuǎn)換
成我們想要的東西遥皂,我們也會想要把我們RequestBody程序里的東西轉(zhuǎn)換成后端想要的東西.就是這個邏輯拉,這個工廠類就是給我們提供各種轉(zhuǎn)換器氮发,我們
只需要根據(jù)我們自己的需求來實(shí)現(xiàn)或者使用對應(yīng)的就好了渴肉。這又是啥冗懦,還是和上面一樣啊爽冕,給你定義一個接口,接口是什么披蕉,就是標(biāo)準(zhǔn)颈畸,給你一個標(biāo)準(zhǔn)
你實(shí)現(xiàn)這個標(biāo)準(zhǔn)就行,我用我這套標(biāo)準(zhǔn)來實(shí)現(xiàn)我內(nèi)部的邏輯没讲,至于你怎么實(shí)現(xiàn)眯娱,想用啥方法實(shí)現(xiàn),玩成什么花樣都可以爬凑,我不管徙缴,只要你遵循了標(biāo)準(zhǔn),就可以嘁信。這樣
擴(kuò)展性就好呀于样。這就是人家大神牛逼之處啊,代碼寫到高處就是寫標(biāo)準(zhǔn)啊潘靖。
講到這里穿剖,我們示例用法中的第一句Retrofit retrofit = new Retrofit.Builder().baseUrl("xxx").build();總算講完了。中間這么多邏輯卦溢,這么
多心血糊余,你看,你一句話就搞定了单寂,是不是該學(xué)習(xí)學(xué)習(xí)贬芥。

代理

build好了之后,就是需要的材料都搞齊了宣决,要工廠有工廠要材料有材料蘸劈,下面我們來講講這第二句,第二句疲扎,那厲害了昵时。其實(shí)他就是啥捷雕,利用你定義的一個充滿各種注解的接口interface GitHub()來簡單粗暴的做了一個動作,
那就是create()壹甥。這個動作看似簡單救巷,實(shí)則過于粗暴啊,進(jìn)去看看代碼

public <T> T create(final Class<T> service) {
  1.
    Utils.validateServiceInterface(service);
  2.
    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 {
            3.
            // 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);
            }
            4.
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            5.
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            6.
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

這里你首先要了解的知識是泛型句柠,反射浦译,動態(tài)代理。如果不懂溯职,請自行g(shù)oogle.好吧精盅,我說下動態(tài)代理,動態(tài)代理就是動態(tài)的代理谜酒,就是只要你實(shí)現(xiàn)了一個借口叹俏,Proxy就可以根據(jù)這個接口來對你
實(shí)現(xiàn)代理,也就是說Proxy只能代理實(shí)現(xiàn)了接口的類僻族。這也就是為什么我們要寫一個Interface來作為Service,然后在里面寫一些注解之類的粘驰。如果接觸過JAVAEE的話,
Spring里的AOP動態(tài)代理是采用cglib來修改字節(jié)碼實(shí)現(xiàn)的動態(tài)代理述么,而且不需要實(shí)現(xiàn)接口蝌数,感興趣的朋友可以看一下《让兀回到這里顶伞,就是通過Proxy這個類利用反射,對你寫的接口進(jìn)行解析
獲取到你申明的方法剑梳,然后對你的方法實(shí)現(xiàn)框架想要實(shí)現(xiàn)的邏輯唆貌,來完成所謂的代理。
我們來看代碼阻荒。

  • 第一步挠锥,就是檢驗(yàn)?zāi)愣x的service接口是不是正確。簡單看下代碼,首先如果不是接口會拋出異常侨赡,還有為了避免出現(xiàn)bug,和保證API都是統(tǒng)一的標(biāo)準(zhǔn)蓖租,不允許定義的Service接口繼承別的接口
static <T> void validateServiceInterface(Class<T> service) {
    if (!service.isInterface()) {
      throw new IllegalArgumentException("API declarations must be interfaces.");
    }
    // Prevent API interfaces from extending other interfaces. This not only avoids a bug in
    // Android (http://b.android.com/58753) but it forces composition of API declarations which is
    // the recommended pattern.
    if (service.getInterfaces().length > 0) {
      throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
    }
  }
  • 第二步,如果你在前面creat()的時候羊壹,設(shè)置過validateEagerlytrue的話蓖宦,它會在這一步將所有的你Service中聲明的Method在這里都初始化了,并且緩存起來
private void eagerlyValidateMethods(Class<?> service) {
    Platform platform = Platform.get();
    for (Method method : service.getDeclaredMethods()) {
      if (!platform.isDefaultMethod(method)) {
        loadServiceMethod(method);
      }
    }
  }

  ServiceMethod<?, ?> loadServiceMethod(Method method) {
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;

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

這里在解析你用annotations標(biāo)注的Method時也一樣用到了Builder這種模式,通過ServiceMethod這個類來解析你的標(biāo)注油猫,將標(biāo)準(zhǔn)轉(zhuǎn)化為實(shí)際的邏輯稠茂。
這里面的代碼比較多,我就不再貼了,其實(shí)里面的邏輯比較單一睬关,但是比較復(fù)雜诱担。主要就是根據(jù)不同的標(biāo)注,來生成對應(yīng)的對象电爹,你用著有多簡單就有框架來給你承受多復(fù)雜蔫仙。只看一下他的Constructor
最后會得到著一些東西。

  ServiceMethod(Builder<R, T> builder) {
    this.callFactory = builder.retrofit.callFactory();
    this.callAdapter = builder.callAdapter;
    this.baseUrl = builder.retrofit.baseUrl();
    this.responseConverter = builder.responseConverter;
    this.httpMethod = builder.httpMethod;
    this.relativeUrl = builder.relativeUrl;
    this.headers = builder.headers;
    this.contentType = builder.contentType;
    this.hasBody = builder.hasBody;
    this.isFormEncoded = builder.isFormEncoded;
    this.isMultipart = builder.isMultipart;
    this.parameterHandlers = builder.parameterHandlers
  }
  • 第三步丐箩,這時候就進(jìn)入到每個方法的代理實(shí)現(xiàn)里來了摇邦。實(shí)際上這里面是已經(jīng)進(jìn)入了上面例子中的第三句了,因?yàn)槭菫槊恳粋€其中的方法實(shí)現(xiàn)代理Call<List<Integer>> call = gitHub.contributors("xx", "xx");的流程了屎勘。
    如果是Object聲明的方法施籍,直接執(zhí)行原方法,然后platform.isDefaultMethod(method)Android平臺直接返回false概漱,所以這里直接忽略丑慎。
  • 第四步,這里如果第二步?jīng)]有build過這個方法犀概,或者緩存里沒有會build這個方法立哑,緩存里有的話直接取過來。
  • 第五步姻灶,根據(jù)serviceMethod初始化OkHttpCall,真正執(zhí)行請求是交給這個類來執(zhí)行的。
  • 第六步诈茧,根據(jù)OkHttpCall最后返回CallAdapter適配后的你想要的類型.到這里就通過代理得到了一個所有參數(shù)产喉,headers或者其他都準(zhǔn)備好了的,并且也通過CallAdapter實(shí)現(xiàn)了返回?cái)?shù)據(jù)包裝的一個完整的數(shù)據(jù)類型.

講到這里敢会,準(zhǔn)備工作都已經(jīng)做齊了曾沈,就等著最后執(zhí)行了。這里的Call是根據(jù)你設(shè)置的CallAdapter來返回的鸥昏,比如如果你熟悉Rxjava塞俱,那結(jié)合Rxjava,這里也可以
返回一個Observable.當(dāng)然你在定義這個Service接口的時候也應(yīng)該聲明為這個返回類型吏垮。就算是Call ,也不是返回OkHttpCall,前面講到了ExecutorCallbackCall來靜態(tài)代理了
OkHttpCall障涯,實(shí)際上這里返回的是ExecutorCallbackCall.

執(zhí)行

如果是ExecutorCallbackCall的話,提供了同步的excute和異步的enqueue來執(zhí)行這個請求膳汪,并且提供一個Callback回調(diào)的接口來處理調(diào)用成功
或者失敗唯蝶。調(diào)用之后是如何拿到數(shù)據(jù)之后,被Converter轉(zhuǎn)化遗嗽,被CallAdapter包裝然后返回給我們的呢粘我?
來我們慢慢分析。前面我們提到了痹换,其實(shí)所有的請求執(zhí)行征字,實(shí)際上都是OkHttpCall這個類在操作都弹。OkHttpCall實(shí)現(xiàn)了Call接口,就是一些請求的常用邏輯匙姜,同步異步cancel等等缔杉,
不管是同步還是異步,最后都是拿到返回的Response轉(zhuǎn)換成我們想要的數(shù)據(jù)搁料。我們挑一個OkHttpCall中同步的方法看看:

  @Override 
  public Response<T> execute() throws IOException {
      okhttp3.Call call;

      synchronized (this) {
        ... 中間邏輯很簡單就省略了

      return parseResponse(call.execute());
     }
  }


 Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();
    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) {
      rawBody.close();
      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;
    }
  }

首先我們就來看Retrofit在執(zhí)行后是怎么講response轉(zhuǎn)換成我們想要的數(shù)據(jù)的或详。excute()執(zhí)行后中間有點(diǎn)失敗取消的邏輯,最后就是直接把成功后的response交給
parseResponse()這個方法郭计,這里先轉(zhuǎn)化為一個沒有body數(shù)據(jù)的response來做狀態(tài)判斷霸琴,如果需要轉(zhuǎn)換數(shù)據(jù),把原來的ResponseBody轉(zhuǎn)換為一個靜態(tài)代理的ExceptionCatchingRequestBody
交給serviceMethod.toResponse(catchingBody)昭伸,主要是為了做一些異常處理梧乘。順著這個流程我們進(jìn)ServiceMethod來看看toResponse()這個方法。

/** Builds a method return value from an HTTP response body. */
 public ServiceMethod build() {
   ...
    responseConverter = createResponseConverter();
    ...
 }

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

 

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

很簡單就是交給了Converter來做轉(zhuǎn)換庐杨。Converter看起來是不是很眼熟选调。前面我們好像設(shè)置了啊。最后又回到了Retrofit這個類灵份,來看看
responseBodyConverter()這個方法:

  public <T> Converter<T, RequestBody> requestBodyConverter(Type type,
      Annotation[] parameterAnnotations, Annotation[] methodAnnotations) {
    return nextRequestBodyConverter(null, type, parameterAnnotations, methodAnnotations);
  }

  public <T> Converter<T, RequestBody> nextRequestBodyConverter(Converter.Factory skipPast,
      Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations) {
    checkNotNull(type, "type == null");
    checkNotNull(parameterAnnotations, "parameterAnnotations == null");
    checkNotNull(methodAnnotations, "methodAnnotations == null");

    int start = converterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = converterFactories.size(); i < count; i++) {
      Converter.Factory factory = converterFactories.get(i);
      Converter<?, RequestBody> converter =
          factory.requestBodyConverter(type, parameterAnnotations, methodAnnotations, this);
      if (converter != null) {
        //noinspection unchecked
        return (Converter<T, RequestBody>) converter;
      }
    }

   ...build string
    throw new IllegalArgumentException(builder.toString());
  }

其實(shí)很簡單仁堪,就是返回factory.requestBodyConverter(type, parameterAnnotations, methodAnnotations, this);,就是工廠造一個Converter
這個工廠造的Converter怎么造填渠,框架是不管的弦聂,總之你按照我給你定義的標(biāo)準(zhǔn)造一個來就是了。感興趣就去看看'retrofit-converters'這個包里是怎么造的氛什,也很簡單
然后通過Converterconvert()方法就把你想要的類型數(shù)據(jù)返回給你了莺葫,這個convert()方法也是你在實(shí)現(xiàn)Converter要自己實(shí)現(xiàn)的,當(dāng)然源碼里提供了一些實(shí)現(xiàn)枪眉,你自己去看捺檬。

整個流程就是這樣的。希望對你閱讀源代碼有幫助贸铜。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末堡纬,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子萨脑,更是在濱河造成了極大的恐慌隐轩,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件渤早,死亡現(xiàn)場離奇詭異职车,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門悴灵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來扛芽,“玉大人,你說我怎么就攤上這事积瞒〈猓” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵茫孔,是天一觀的道長叮喳。 經(jīng)常有香客問我,道長缰贝,這世上最難降的妖魔是什么馍悟? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮剩晴,結(jié)果婚禮上锣咒,老公的妹妹穿的比我還像新娘。我一直安慰自己赞弥,他們只是感情好毅整,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著绽左,像睡著了一般悼嫉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上妇菱,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天承粤,我揣著相機(jī)與錄音,去河邊找鬼闯团。 笑死,一個胖子當(dāng)著我的面吹牛仙粱,可吹牛的內(nèi)容都是我干的房交。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼伐割,長吁一口氣:“原來是場噩夢啊……” “哼候味!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起隔心,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤白群,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后硬霍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體帜慢,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了粱玲。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片躬柬。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖抽减,靈堂內(nèi)的尸體忽然破棺而出允青,到底是詐尸還是另有隱情,我是刑警寧澤卵沉,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布颠锉,位于F島的核電站,受9級特大地震影響史汗,放射性物質(zhì)發(fā)生泄漏琼掠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一淹办、第九天 我趴在偏房一處隱蔽的房頂上張望眉枕。 院中可真熱鬧,春花似錦怜森、人聲如沸速挑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽姥宝。三九已至,卻和暖如春恐疲,著一層夾襖步出監(jiān)牢的瞬間腊满,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工碳蛋, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人省咨。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓肃弟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親零蓉。 傳聞我的和親對象是個殘疾皇子笤受,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

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