Retorfit源碼學習

Retorfit源碼學習


一.什么是Retorfit

  • 簡單的來說Retorfit是封裝到Okhttp的一個網(wǎng)絡請求庫,方便客戶端調用去請求,返回的數(shù)據(jù)方便客戶端解析,支持Rxjava鏈式調用,內部通過動態(tài)代理+自定義注解方式去獲取客戶端定義的方法和方法中定義的注解,參數(shù)等,交給Okhttp請求,拿到結果通過數(shù)據(jù)轉換工廠去轉換,通過Rxjava->Observable去發(fā)射真正的網(wǎng)絡請求也就是Okhttp,客戶端拿到發(fā)射的事件流做相應的操作即可。那么在源碼分析之前先來看看在使用GsonConverterFactory和RxJavaCallAdapterFactory時,請求的例子。

二.請求實例

1.創(chuàng)建retorfit實例

 private HttpClient() {
        client = new OkHttpClient.Builder()
                .connectTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .addInterceptor(new LogInterceptor())
                .build();
        retrofit = new Retrofit.Builder()
                .baseUrl(Constants.SERVER_URL)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        apiService = retrofit.create(MedexApiService.class);

    }
  • 可以看到Retorfit創(chuàng)建時是通過Builder模式去構建實例的,何為Builder模式,簡單說明下Builder模式可以將一個類的構建和表示進行分離。說白了,也就是減少對象創(chuàng)建過程中引入的多個構造函數(shù)、可選參數(shù)以及多個 set方法 過度使用導致的不必要的復雜性。

2.定義接口

public interface MedexApiService {
    @FormUrlEncoded
    @POST("./")
    Observable<BaseResponse<Logindata>> login(@FieldMap Map<String, String> params);
}

3.客戶端調用

    ...此處省略代碼
    HttpClient.getInstance().
                 getMedexApiService().
                 login(ParamsTool.getParms(params))
    ...此處省略代碼

一次請求就這么完美的執(zhí)行了,配合rxjava簡直爽的不要不要的。那么它內部是如何處理傳遞的參數(shù),和拿到參數(shù)后如何去請求,拿到結果后如何轉換為客戶端定義的類型,轉換類型后又如何包裝成rxjava Observable的,帶著一些列問題,我們去探探究竟。

三.源碼分析

從上面例子已經看出創(chuàng)建Retorfit實例時,通過Builder設置一些參數(shù),那么這些參數(shù)用來干什么的,有什么用,它內部又如何設置這些值。帶著疑問我們來看看new Builder和Builder中設置的這些參數(shù)用來干什么。

1.builder初始化及一些set方法

  • newBuilder
  public Builder() {
      //調用Platform.get()
      this(Platform.get());
  }
  //Platform.class
  private static final Platform PLATFORM = findPlatform();
  //get方法調用findPlatform返回一個Platform 
  static Platform get() {
    return PLATFORM;
  }
 //可以看到findPlatform方法根據(jù)不同平臺返回不同的Platform,那我們直接來看
 //new Android()這塊
 private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("java.util.Optional");
      return new Java8();
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("org.robovm.apple.foundation.NSObject");
      return new IOS();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }
 //Android繼承自Platform
 static class Android extends Platform {
   //可以當作是用來線程切換的執(zhí)行器
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }
    //默認的網(wǎng)絡發(fā)射器,RxJavaCallAdapterFactory就是CallAdapter.Factory的具體工廠,如果外部不提供就用這個默認的,具體ExecutorCallAdapterFactory源碼這里不做分析,只分析RxJavaCallAdapterFactory。
    @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }
    //回調方法執(zhí)行器,作用是用來線程切換的。
    static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());
      //在Retorfit中默認是將okhttp請求的返回的數(shù)據(jù)切換到主線程中
      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }
  //最終調用Builder的第二個構造方法,并且添加默認的數(shù)據(jù)轉換器
   Builder(Platform platform) {
      this.platform = platform;
      converterFactories.add(new BuiltInConverters());
    }
  • baseUrl()
   public Builder baseUrl(String baseUrl) {
      //檢測url合法性
      checkNotNull(baseUrl, "baseUrl == null");
      //外部傳進來的String url 轉換為Okhttp中認可的HttpUrl
      HttpUrl httpUrl = HttpUrl.parse(baseUrl);
      if (httpUrl == null) {
        throw new IllegalArgumentException("Illegal URL: " + baseUrl);
      }
      return baseUrl(httpUrl);
    }
   public Builder baseUrl(HttpUrl baseUrl) {
      checkNotNull(baseUrl, "baseUrl == null");
      //得到url的分片
      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;
    }
  • client()
  //設置okhttpClient
  public Builder client(OkHttpClient client) {
      return callFactory(checkNotNull(client, "client == null"));
    }
   //檢查合法性并賦值給 Budiler中  callFactory
    public Builder callFactory(okhttp3.Call.Factory factory) {
      this.callFactory = checkNotNull(factory, "factory == null");
      return this;
    }
  • addConverterFactory()
    public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }
  • 設置轉換器,可以看到參數(shù)需要一個轉換工廠,Converter.Factory,我們傳進來的是一個GsonConverterFactory具體的工廠,這里Retorfit用到的是工廠方法設計模式,那先來看看Converter.Factory 定義的工廠方法都有哪些。
    關于工廠設計模式請參考此文章
 //將HTTP響應主體轉換為? 也就是我們代碼中定義的類型
 public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
        Retrofit retrofit) {
      return null;
    }
   //將代碼中請求的類型轉換為HTTP請求體
   //主要用于對Part、PartMap、Body注解的處理
    public Converter<?, RequestBody> requestBodyConverter(Type type,
        Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
      return null;
    }
    // 這里用于對Field、FieldMap、Header、Path、Query、QueryMap注解的理
    // Retrfofit對于上面的幾個注解默認使用的是調用toString方法
    public Converter<?, String> stringConverter(Type type, Annotation[] annotations,
        Retrofit retrofit) {
      return null;
    }
  • 以上三個方法都是解析收據(jù)時用到的,具體實現(xiàn)在創(chuàng)建Retorfit時傳入的GsonConverterFactory中,可自行查閱Gosn解析的一些api。

addCallAdapterFactory()

public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      adapterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }
  • 將RxJavaCallAdapterFactory實例添加到adapterFactories集合中,和添加解析器一樣,也是一個工廠方法設計模式,那我們看看CallAdapter.Factory中定義的重要方法
//根據(jù)方法返回類型和方法上定義的注解返回CallAdapter,具體的CallAdapter在RxJavaCallAdapterFactory 中內部類SimpleCallAdapter實現(xiàn),這里只針對,定義接口中返回Observable<BaseResponse>來說明
public abstract CallAdapter<?> get(Type returnType, Annotation[] annotations,Retrofit retrofit);

最后我們來看下build完成構建后的代碼

 public Retrofit build() {
      //檢查是否設置了baseUrl
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
      okhttp3.Call.Factory callFactory = this.callFactory;
      //檢查是否設置了OkhttpClient,如果沒有new一個
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }
      //回調方法執(zhí)行器是否為null,如果我們沒調用set設置那么默認為null
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
      //生成默認的回調方法執(zhí)行器,默認的回調方法執(zhí)行器就是                      //MainThreadExecutor                   
        callbackExecutor = platform.defaultCallbackExecutor();
      }
      //講adapterFactories集合中添加的數(shù)據(jù)復制到新的集合中,adapterFactories添加是我們外部傳進來的RxJavaCallAdapterFactory

      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);

//在新的集合中又添加一個默認的網(wǎng)絡發(fā)射器具體請查看Android中的defaultCallAdapterFactory方法,那么網(wǎng)絡發(fā)射器集合中目前有兩個。第一個是 RxJavaCallAdapterFactory。第二個是默認的網(wǎng)絡發(fā)射器。  
  
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      //上文中已經說明在Builder有參構造中已添加了一個默認的數(shù)據(jù)轉換器,那么我們在外部又添加了一個GsonConverterFactory,那么這個轉換器集合中有兩個。第一個是默認的轉換器,第二個是外部提供的GsonConverterFactory

      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

     //構造Retrofit實例,并且把Builder中設置的參數(shù)傳遞給Retrofit

     return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
    }
  • 上面我們分析了創(chuàng)建Retorfit時都干了什么,大致總結一下,當newBuilder時,創(chuàng)建默認的數(shù)據(jù)轉換器。調用Builder一系列set方法設置GsonConverterFactory數(shù)據(jù)轉換器,設置RxjavaCallAdapter網(wǎng)絡發(fā)射器,設置OkHttpClient,構造Builder時,把設置的兩個工廠(GsonConverterFactory轉換器和RxjavaCallAdapter網(wǎng)絡發(fā)射器)加入到各自集合中,那么此時兩個集合中各自的數(shù)量都是兩個,一個是默認的,一個是外部我們自己傳遞進來的,把這些參數(shù)通過Retorfit構造方法并傳遞個Retorfit。

上面我們大致說了下設置數(shù)據(jù)轉換器(GsonConverterFactory)和設置網(wǎng)絡發(fā)射器(RxjavaCallAdapter),以及默認的數(shù)據(jù)轉換器(BuiltInConverters)和網(wǎng)絡發(fā)射器(ExecutorCallAdapterFactory),那么接下來,講分析Retorfit中的create方法了。

2.Retorfit的create方法都干了什么。

 public <T> T create(final Class<T> service) {
    //驗證是否是接口
    Utils.validateServiceInterface(service);
    //是否提前預加載接口中的所有方法,并且緩存??梢酝ㄟ^Builder去set設置
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    //創(chuàng)建代理類
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() {
          private final Platform platform = Platform.get();
//這個 invoke方法是在代理類調用最終對象的方法時,會調用此方法。
//proxy 是代理對象,method是被代理方法,args 被代理參數(shù)
 @Override 
 public Object invoke(Object proxy, Method method, Object... args)   throws Throwable {
    if (method.getDeclaringClass() == Object.class) {
     return method.invoke(this, args);
    }
    //默認值是false先不管(Platform類中是false,默認的Android繼承于Platform,但是并沒有去重寫此方法,所以該方法返回false)

    if (platform.isDefaultMethod(method)) {
    return platform.invokeDefaultMethod(method, service, proxy, args);
    }
    //重點 1
    //解析method中的注解,得到注解中的參數(shù)。
    //初始化數(shù)據(jù)解析器,初始化網(wǎng)絡發(fā)射器
    //ServiceMethod 可以說是封裝了請求的所有參數(shù)。
    ServiceMethod serviceMethod = loadServiceMethod(method);
    //重點2 構建Okhttp請求,真正去請求網(wǎng)絡的執(zhí)行器。
    OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
    //重點3 包裝網(wǎng)絡請求執(zhí)行器交給網(wǎng)絡發(fā)射器來操作。
    return serviceMethod.callAdapter.adapt(okHttpCall);
    }
   });
}

從以上分析可知到,當調用Retorfit中的create方法時,創(chuàng)建代理類,當調用接口中定義的方法時,其實就會調用代理類的 invoke 方法,在此方法中,Retorfit攔截并做了三件事。

  1. 解析代理方法中的method 注解 ,包括method上的注解和method參數(shù)注解,并做了相應的緩存,創(chuàng)建外部設置進來的數(shù)據(jù)解析器GsonConverterFactory.create(),和網(wǎng)絡發(fā)射器RxJavaCallAdapterFactory.create()。
  2. 創(chuàng)建OkhttpCall 這個類是真正去執(zhí)行網(wǎng)絡操作的類。并且把封裝好的解析器GsonConverterFactory.create(),和發(fā)射器RxJavaCallAdapterFactory.create()的ServiceMethod 和方法中的參數(shù)傳遞給它。
  3. 將創(chuàng)建的okhttpCall對象交給網(wǎng)絡發(fā)射器來發(fā)射也就是我們在創(chuàng)建Retorfit時傳進來的RxJavaCallAdapterFactory.create()
    那么接下來對上文標注的重點一一分析。

3.ServiceMethod 都干了什么。

 ServiceMethod serviceMethod = loadServiceMethod(method);

當調用loadServiceMethod 時,傳遞的是我們接口中定義的方法。LoadServiceMethod方法代碼如下:

  ServiceMethod loadServiceMethod(Method method) {
    ServiceMethod result;
      synchronized (serviceMethodCache) {
     //先在緩存中找,key是接口中定義的method,值是ServiceMethod 
      result = serviceMethodCache.get(method);
      if (result == null) {
       //如果沒找到,那么就去構建一個,并且緩存
        result = new ServiceMethod.Builder(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }
  • 此方法說明了,在調用retorfit.create方法時,為什么我們有時會創(chuàng)建一個單例的實例,代理對象是單例的,那么足可以說該實例中的方法也是唯一的,所以,在這一步起到緩存的作用。

3.1 ServiceMethod.Builder(this, method)

將Retofit實例以及被代理方法傳遞給ServiceMethod中的Builder.

    public Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      //獲取method上定義的注解
      this.methodAnnotations = method.getAnnotations();
      //獲取method中參數(shù)類型
      this.parameterTypes = method.getGenericParameterTypes();
      //獲取method中參數(shù)注解
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

再看.build()方法

      public ServiceMethod build() {
      //重點1.1 創(chuàng)建網(wǎng)絡發(fā)射器
      callAdapter = createCallAdapter();
      //返回類型
      responseType = callAdapter.responseType();
      ...省略一些判斷代碼
      //重點1.2創(chuàng)建相應的數(shù)據(jù)轉換器
      responseConverter = createResponseConverter();
      //遍歷method上的的注解并解析
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }
     ...省略一些判斷
     //得到方法注解參數(shù)長度
      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      //遍歷方法注解參數(shù)并解析封裝在parameterHandlers數(shù)組中
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
       ...省略代碼
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }
      ...省略代碼
      //返回ServiceMethod實例
      return new ServiceMethod<>(this);
    }

針對上面創(chuàng)建ServiceMethod時,標注的重點看下

3.1.1 創(chuàng)建網(wǎng)絡發(fā)射器
   private CallAdapter<?> createCallAdapter() {
      //獲取method返回值類型
      Type returnType = method.getGenericReturnType();
      ...省略判斷
      //獲取method上的注解
      Annotation[] annotations = method.getAnnotations();
      try {
        //調用retrofit中的callAdapter
        return retrofit.callAdapter(returnType, annotations);
      } catch (RuntimeException e) { 
        throw methodError(e, "Unable to create call adapter for %s", returnType);
      }
    }

接著看retrofit.callAdapter方法

  //內部調用nextCallAdapter方法
  public CallAdapter<?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }
  
  public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
   ...省略判斷
    //傳入的skipPast是null那么adapterFactories.indexOf(skipPast)得到的是-1,
    //那么start就是0,也就是從0開始遍歷我們剛開始在Builder構建出的網(wǎng)絡發(fā)射器集合,
    //并且調用這個網(wǎng)絡發(fā)射器集合的get方法把返回類型,和方法上的注解還有Retorfit傳遞過去。并且返回CallAdapter<?>接口。
    //由于RxJavaCallAdapterFactory實現(xiàn)了CallAdapter接口,
    //上文中也提到,通過Retorfit.Builder傳遞進來的RxjavaCallAdapter在集合的第一個,
    //所以我們著重看下,RxjavaCallAdapter.get()方法實現(xiàn)。

    int start = adapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = adapterFactories.size(); i < count; i++) {
      CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }
 ...省略代碼
 }
 //RxjavaCallAdapter.java
 @Override
  public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    Class<?> rawType = getRawType(returnType);
    String canonicalName = rawType.getCanonicalName();
    boolean isSingle = "rx.Single".equals(canonicalName);
    boolean isCompletable = "rx.Completable".equals(canonicalName);
    if (rawType != Observable.class && !isSingle && !isCompletable) {
      return null;
    }
    ..省略一些判斷方法,
    //因為這里我們只分析返回接口中定義的返回Observable
    CallAdapter<Observable<?>> callAdapter = getCallAdapter(returnType, scheduler);
    return callAdapter;
  }
  
  //可以看到調用了getCallAdapter()方法,繼續(xù)看getCallAdapter()方法
  
  private CallAdapter<Observable<?>> getCallAdapter(Type returnType, Scheduler scheduler) {
    //根據(jù)返回的泛型type得到Observable中定義的泛型參數(shù)type
    Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
    //根據(jù)泛型參數(shù)type得到參數(shù)Class
    Class<?> rawObservableType = getRawType(observableType);
    //Observable中的泛型是否是Response
    if (rawObservableType == Response.class) {
      ...省略驗證代碼
      Type responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
      return new ResponseCallAdapter(responseType, scheduler);
    }
     //Observable中的泛型是否是Result
    if (rawObservableType == Result.class) {
      ...省略驗證代碼
      Type responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
      return new ResultCallAdapter(responseType, scheduler);
    }
    //由于我們給的例子是Observable中的泛型參數(shù)是我們自己定義的對象,
    //那么最終返回SimpleCallAdapter
    return new SimpleCallAdapter(observableType, scheduler);
  }
 

至此我們上文中標注的1.1重點已分析完,大致總結下:在ServiceMethod調用Builder時,調用了createCallAdapter,而createCallAdapter又調用了Retorfit中的callAdapter方法,callAdapter內部調用nextCallAdapter方法,再在nextCallAdapter方法中,遍歷我之前在Retorfit構建的網(wǎng)絡發(fā)射器集合,并調用其內部元素的get方法,由于我們設置的RxJavaCallAdapterFactory在集合的首位,所以,我們直接看RxJavaCallAdapterFactory的get方法,根據(jù)我們在代碼中定義的返回值(Observable)以及返回值泛型(BaseResponse)最中調用了并返回了SimpleCallAdapter。那么至此,網(wǎng)絡發(fā)射器具體的實現(xiàn)已找到,接著分析重點2.2。

3.1.2
private Converter<ResponseBody, T> createResponseConverter() {
     //獲取方法上的
      Annotation[] annotations = method.getAnnotations();
     //返回retrofit中responseBodyConverter方法并把接口返回類型和方法上的注解傳遞給它
        return retrofit.responseBodyConverter(responseType, annotations);
        ...省略異常代碼
}        

//Retorfit.java
 public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
    return nextResponseBodyConverter(null, type, annotations);
  }
 //最終調用 nextResponseBodyConverter方法
 public <T> Converter<ResponseBody, T> nextResponseBodyConverter(Converter.Factory skipPast,
      Type type, Annotation[] annotations) {
    ...省略合法性代碼
    //因為skipPast傳遞的是null,那么start也是從0開始,
    //那么集合中第一個元素的BuiltInConverters,而BuiltInConverters實現(xiàn)了responseBodyConverter,由于其內部根據(jù)判斷沒有我們想要的返回類型,
    //所以最終返回null。接著遍歷第二個元素,也就是我們外部設置進來的GsonConverterFactory中的responseBodyConverter方法,
    //最終返回GsonResponseBodyConverter這個對象。
    int start = converterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = converterFactories.size(); i < count; i++) {
      Converter<ResponseBody, ?> converter =
          converterFactories.get(i).responseBodyConverter(type, annotations, this);
      if (converter != null) {
        return (Converter<ResponseBody, T>) converter;
      }
    }
    ...省略異常代碼
  }
  • 總結一下,當創(chuàng)建響應數(shù)據(jù)轉換時,遍歷數(shù)據(jù)轉換集合,判斷,驗證我們的返回類型,由于默認的相應數(shù)據(jù)轉換器(BuiltInConverters),在responseBodyConverter方法中沒有我們想要的返回類型,所以最終返回null,那么在遍歷第二個元素時,也就是外部提供的GsonConverterFactory,其內部responseBodyConverter方法返回GsonResponseBodyConverter 這個類對象,所以,得到一條結論,在我們上述定義的請求例子中,當網(wǎng)絡請求完畢后,數(shù)據(jù)轉換在GsonResponseBodyConverter中操作的。

至此,構建ServiceMethod源碼已分析完。根據(jù)上面分析ServiceMethod構建時,完成了網(wǎng)絡發(fā)射器的創(chuàng)建和響應數(shù)據(jù)轉換器的創(chuàng)建,以及方法上方法參數(shù)中的注解解析。所以,ServiceMethod是封裝了網(wǎng)絡請求的所有參數(shù)以及網(wǎng)絡請求數(shù)據(jù)的轉換和網(wǎng)絡請求發(fā)射器。

4.創(chuàng)建OkHttpCall

  //把封裝好的所有網(wǎng)絡請求相關的數(shù)據(jù)轉換器和網(wǎng)絡發(fā)射器傳遞給OkHttpCall,以及方法中定義的參數(shù)。
 OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
 
  //接著看OkhttpCall類中關鍵方法
   @Override 
   public synchronized Request request() {
    okhttp3.Call call = rawCall;
    //默認為null
    if (call != null) {
      return call.request();
    }

    try {
     //創(chuàng)建okhttpCall對象并調用okhttp的request方法
      return (rawCall = createRawCall()).request();
    } catch (RuntimeException e) {
      creationFailure = e;
      throw e;
    } catch (IOException e) {
      creationFailure = e;
      throw new RuntimeException("Unable to create request.", e);
    }
  }
  //創(chuàng)建okhttp3.Call
  private okhttp3.Call createRawCall() throws IOException {
   //內部通過ServiceMethod類中的方法構建一個Request
    Request request = serviceMethod.toRequest(args);
    //調用我們通過Retorfit Buidler傳遞進來的OkhttClient對象的newCall方法,創(chuàng)建okhttp3.Call
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }
  //就著看真正去請求的操作(這里我們只說同步請求)
    @Override 
    public Response<T> execute() throws IOException {
    okhttp3.Call call;
    synchronized (this) {
     ...省略判斷
      call = rawCall;
      if (call == null) {
        try {
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException e) {
          creationFailure = e;
          throw e;
        }
      }
    }
    if (canceled) {
      call.cancel();
    }
    //解析數(shù)據(jù),拿到結果后最終會調用GsonResponseBodyConverter中的convert方法進行數(shù)據(jù)轉換。
    return parseResponse(call.execute());
  }

至此OkhttpCall中請求和相應的代碼已分析完。解析來看最后一步,也就是網(wǎng)絡發(fā)射器代碼。

5.網(wǎng)絡發(fā)射器

上文中標注的重點3代碼如下

serviceMethod.callAdapter.adapt(okHttpCall)

上面我們分析了ServiceMethod構建源碼,所以我們知道這個callAdapter就是SimpleCallAdapter,那么直接看SimpleCallAdapter中的adapt方法源碼。

 @Override 
 public <R> Observable<R> adapt(Call<R> call) {
      //創(chuàng)建Observable并發(fā)射CallOnSubscribe中的事件。
      Observable<R> observable = Observable.create(new CallOnSubscribe<>(call)) //
          .flatMap(new Func1<Response<R>, Observable<R>>() {
            @Override 
            public Observable<R> call(Response<R> response) {
              if (response.isSuccessful()) {
                return Observable.just(response.body());
              }
              return Observable.error(new HttpException(response));
            }
          });
      //默認為null      
      if (scheduler != null) {
        return observable.subscribeOn(scheduler);
      }
      return observable;
    }
  }
  //看看CallOnSubscribe中的實現(xiàn)
   static final class CallOnSubscribe<T> implements Observable.OnSubscribe<Response<T>> {
    private final Call<T> originalCall;
   //得到OkhttpCall的引用
    CallOnSubscribe(Call<T> originalCall) {
      this.originalCall = originalCall;
    }

    @Override public void call(final Subscriber<? super Response<T>> subscriber) {
      final Call<T> call = originalCall.clone();
      
     //把OkhttpCall加入到subscriptions集合中用于下面判斷是否取消訂閱
     //ubscriber.isUnsubscribed(),其實就是是否取消網(wǎng)絡請求。
     //當客戶端調用ubscriber.unsubscribed時,其實調用了call.cancel();
     
      subscriber.add(Subscriptions.create(new Action0() {
        @Override public void call() {
          call.cancel();
        }
      }));

      try { 
        //開始同步執(zhí)行,所以如果接口中定義的是Observable返回的話,那么就會執(zhí)行同步請求,
        //所以我們在代碼中往往會寫指定在子線程中發(fā)射事件,在主線程中消費時間,因為是同步請求嘛。
        Response<T> response = call.execute();
        if (!subscriber.isUnsubscribed()) {
         //調用onNext
          subscriber.onNext(response);
        }
      } catch (Throwable t) {
        Exceptions.throwIfFatal(t);
        //出現(xiàn)異常,那么調用onError
        if (!subscriber.isUnsubscribed()) {
          subscriber.onError(t);
        }
        return;
      }
     //最終調用onCompleted
      if (!subscriber.isUnsubscribed()) {
        subscriber.onCompleted();
      }
    }
  }

至此,Retorfit源碼中主要流程分析完畢,關鍵分析點上面已標出,其他代碼還是根據(jù)實際情況來分析,如果客戶端沒有用到rxjava+Retorfit,用Retorfit自帶的Call,那么分析流程就不一樣了,或者用到其他數(shù)據(jù)轉換器,亦或者,接口中定義的不是Observable,而是Completable或者Single。

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

相關閱讀更多精彩內容

  • 簡介 剛接觸Retrofit的時候,就寫了一篇簡單的使用介紹:Retrofit 2.0基本使用方法,算是對Retr...
    Whyn閱讀 3,104評論 4 24
  • 前言 在Android開發(fā)中,網(wǎng)絡請求十分常用 而在Android網(wǎng)絡請求庫中,Retrofit是當下最熱的一個網(wǎng)...
    Carson帶你學安卓閱讀 71,470評論 48 395
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,525評論 19 139
  • 一.Retrofit中Builder模式完成初始化工作 Retrofit現(xiàn)在已經是各種網(wǎng)絡請求類APP的標配了,我...
    Geeks_Liu閱讀 2,106評論 0 9
  • Retrofit這個開源庫出來也有一定年頭了,記得之前還是在V1.0的版本的時候,之前在三月份也寫過一個Retro...
    lovejjfg閱讀 1,506評論 0 5

友情鏈接更多精彩內容