Retrofit源碼解析

寫(xiě)在前面

retrofit源碼版本2.4.0
前置知識(shí): Java動(dòng)態(tài)代理

從用法開(kāi)始

代碼來(lái)自http://www.itdecent.cn/p/021a2c6e128b

public interface RetrofitService {

    /**
     * 獲取快遞信息
     * Rx方式
     *
     * @param type   快遞類(lèi)型
     * @param postid 快遞單號(hào)
     * @return Observable<PostInfo>
     */
    @GET("query")
    Observable<PostInfo> getPostInfoRx(@Query("type") String type, @Query("postid") String postid);
}
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://www.kuaidi100.com/")
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 支持RxJava
        .build();
RetrofitService service = retrofit.create(RetrofitService.class);
Observable<PostInfo> observable = service.getPostInfoRx("yuantong", "11111111111");
observable.subscribeOn(Schedulers.io()) 
        .observeOn(AndroidSchedulers.mainThread()) 
        .subscribe(new Observer<PostInfo>() { 

            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(PostInfo postInfo) {
                Log.i("http返回:", postInfo.toString() + "");
            }
        });

問(wèn)題有三個(gè):

  • 為什么只是寫(xiě)接口Service就可以實(shí)現(xiàn)網(wǎng)絡(luò)請(qǐng)求, 這個(gè)邏輯是怎樣的?
  • 返回對(duì)象是怎么轉(zhuǎn)成Observable的?
  • 返回對(duì)象ResponseBody怎么通過(guò)Gson轉(zhuǎn)成泛型對(duì)象的?

源碼梳理

Retrofit

Retrofit#create

  public <T> T create(final Class<T> service) {
    //檢查service是否是接口類(lèi)型, 并且service不允許繼承其它接口
    Utils.validateServiceInterface(service);
      //是否提前加載service中的所有方法信息
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    //動(dòng)態(tài)代理
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
            if (method.getDeclaringClass() == Object.class) {
              //如果調(diào)用的是Object中的方法, 則直接調(diào)用該方法
              return method.invoke(this, args);
            }
            //是否是平臺(tái)的默認(rèn)方法
           //Platform是接口, 有Android和Java8兩個(gè)實(shí)現(xiàn)類(lèi)
            //上面的Platform.get()方法會(huì)判斷當(dāng)前的系統(tǒng)類(lèi)型
            //之所以這么處理, 是因?yàn)橄馢ava8那樣, 接口中是支持默認(rèn)方法的
            //如果是默認(rèn)方法, 就直接調(diào)用
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            //加載方法信息(方法參數(shù)/返回值類(lèi)型/注解信息等)
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            //生成OkHttpCall并調(diào)用執(zhí)行
            return serviceMethod.adapt(okHttpCall);
          }
        });
  }

這里重點(diǎn)就是最后的三行方法.

Retrofit#loadServiceMethod

  //動(dòng)態(tài)代理前面執(zhí)行的這個(gè)方法
  //遍歷service中的全部public方法執(zhí)行l(wèi)oadServiceMethod
  private void eagerlyValidateMethods(Class<?> service) {
    Platform platform = Platform.get();
    for (Method method : service.getDeclaredMethods()) {
      if (!platform.isDefaultMethod(method)) {
        loadServiceMethod(method);
      }
    }
  }

//serviceMethodCache緩存信息
  ServiceMethod<?, ?> loadServiceMethod(Method method) {
//serviceMethodCache的類(lèi)型是Map<Method, ServiceMethod<?, ?>>
//如果已經(jīng)加載過(guò), 就從serviceMethodCache取出直接返回
//這也就是執(zhí)行eagerlyValidateMethods的意義
//提前加載
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;

//保證線(xiàn)程按全
//這里是不是很像單例里的雙檢鎖/雙重校驗(yàn)鎖(DCL)
    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        //如果沒(méi)加載過(guò), 就創(chuàng)建ServiceMethod
        //ServiceMethod這里就是保存方法的各個(gè)信息
        result = new ServiceMethod.Builder<>(this, method).build();
        //緩存進(jìn)serviceMethodCache
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

ServiceMethod

ServiceMethod.Builder<>(this, method).build()

    Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      //獲取方法的注解信息, 注解可以有多個(gè), 所以是數(shù)組
      //比如注解@Get @NotNull
      this.methodAnnotations = method.getAnnotations();
      //方法的參數(shù)類(lèi)型
      this.parameterTypes = method.getGenericParameterTypes();
     //方法的參數(shù)中的注解
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

    public ServiceMethod build() {
      //獲取callAdapter 
      //注意這個(gè)方法, 該方法和問(wèn)題2有關(guān)
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }
      //注意這個(gè)方法, 該方法和問(wèn)題3有關(guān)
      responseConverter = createResponseConverter();

      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }

      //...各種檢查

      //Builder模式
      //最終生成ServiceMethod, 將builder中的各個(gè)參數(shù)保存到ServiceMethod中
      return new ServiceMethod<>(this);
    }

看到這里我們大概可以看出, 接口Service中的方法信息被一一對(duì)應(yīng)保存在了對(duì)應(yīng)的ServiceMethod中.

ServiceMethod#adapt

現(xiàn)在回到Retrofit#create方法的最后, 我們調(diào)用了如下方法

            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            //這里尤其要注意的是, adapt的參數(shù)是Call的實(shí)現(xiàn)類(lèi), OkHttpCall, 后面還要用到
            return serviceMethod.adapt(okHttpCall);

下面我們就來(lái)看看 ServiceMethod#adapt

  T adapt(Call<R> call) {
    return callAdapter.adapt(call);
  }

ServiceMethod#adapt方法很簡(jiǎn)單, 就是調(diào)用了CallAdapter#adapt, 而CallAdapter是接口, 這個(gè)時(shí)候我們就需要來(lái)看看這個(gè)callAdapter到底是誰(shuí)了

在ServiceMethod.Builder#build方法中, 我們創(chuàng)建了callAdapter

      callAdapter = createCallAdapter();
    private CallAdapter<T, R> createCallAdapter() {
      //拿到方法的返回值信息
      Type returnType = method.getGenericReturnType();
      if (Utils.hasUnresolvableType(returnType)) {
        throw methodError(
            "Method return type must not include a type variable or wildcard: %s", returnType);
      }
      if (returnType == void.class) {
        throw methodError("Service methods cannot return void.");
      }
      Annotation[] annotations = method.getAnnotations();
      try {
        //noinspection unchecked
        //最終, 我們的callAdapter是在retrofit類(lèi)中獲取
        return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
      } catch (RuntimeException e) { // Wide exception range because factories are user code.
        throw methodError(e, "Unable to create call adapter for %s", returnType);
      }
    }

Retrofit#callAdapter

  public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }

  public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");

    int start = callAdapterFactories.indexOf(skipPast) + 1;
    //遍歷callAdapterFactories, 一個(gè)一個(gè)去找
    //找到就返回
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }
   //...
    //如果沒(méi)找到, 輸出異常信息
  }

如果我們看一下callAdapterFactories, 就會(huì)發(fā)現(xiàn), 這個(gè)Map里的值正是我們?cè)趧?chuàng)建Retrofit的時(shí)候通過(guò)retrofit2.Retrofit.Builder#addCallAdapterFactory方法傳進(jìn)去的RxJavaCallAdapterFactory.create(), 該方法創(chuàng)建了RxJavaCallAdapterFactory, 也就是說(shuō), 通過(guò)retrofit2.adapter.rxjava.RxJavaCallAdapterFactory#get方法, 我們獲取到了真正的CallAdapter

RxJavaCallAdapterFactory#get

  @Override
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    Class<?> rawType = getRawType(returnType);
    boolean isSingle = rawType == Single.class;
    boolean isCompletable = rawType == Completable.class;
    //如果方法的返回值類(lèi)型不是Observable, 也不是Single和Completable
    //就返回空
    //也就是不由RxJavaCallAdapter處理
    if (rawType != Observable.class && !isSingle && !isCompletable) {
      return null;
    }

    //最后, 返回的是RxJavaCallAdapter
    if (isCompletable) {
      return new RxJavaCallAdapter(Void.class, scheduler, isAsync, false, true, false, true);
    }

    //...

    return new RxJavaCallAdapter(responseType, scheduler, isAsync, isResult, isBody, isSingle,
        false);
  }

也即是, 真正的CallAdapter其實(shí)是RxJavaCallAdapter

RxJavaCallAdapter#adapt

現(xiàn)在我們重新回頭來(lái)看retrofit2.ServiceMethod#adapt

  T adapt(Call<R> call) {
    return callAdapter.adapt(call);
  }

我們知道了這里callAdapter是RxJavaCallAdapter, 參數(shù)call是OkHttpCall
所以我們來(lái)看RxJavaCallAdapter#adapt

  //注意, 這里, 也是問(wèn)題2的關(guān)鍵
  @Override public Object adapt(Call<R> call) {
    //如果是異步方法, 就返回CallEnqueueOnSubscribe, 如果是同步, 就返回CallExecuteOnSubscribe
    OnSubscribe<Response<R>> callFunc = isAsync
        ? new CallEnqueueOnSubscribe<>(call)
        : new CallExecuteOnSubscribe<>(call);

    OnSubscribe<?> func;
    if (isResult) {
      func = new ResultOnSubscribe<>(callFunc);
    } else if (isBody) {
      func = new BodyOnSubscribe<>(callFunc);
    } else {
      func = callFunc;
    }
    Observable<?> observable = Observable.create(func);

    if (scheduler != null) {
      observable = observable.subscribeOn(scheduler);
    }

    if (isSingle) {
      return observable.toSingle();
    }
    if (isCompletable) {
      return observable.toCompletable();
    }
    return observable;
  }
final class CallEnqueueOnSubscribe<T> implements OnSubscribe<Response<T>> {
  private final Call<T> originalCall;

  CallEnqueueOnSubscribe(Call<T> originalCall) {
    this.originalCall = originalCall;
  }

  @Override public void call(Subscriber<? super Response<T>> subscriber) {
    // Since Call is a one-shot type, clone it for each new subscriber.
    Call<T> call = originalCall.clone();
    final CallArbiter<T> arbiter = new CallArbiter<>(call, subscriber);
    subscriber.add(arbiter);
    subscriber.setProducer(arbiter);
    //這里, 執(zhí)行了OkHttpCall#enqueue, 拿到返回值后, 通過(guò)arbiter發(fā)射出去
    call.enqueue(new Callback<T>() {
      @Override public void onResponse(Call<T> call, Response<T> response) {
        arbiter.emitResponse(response);
      }

      @Override public void onFailure(Call<T> call, Throwable t) {
        Exceptions.throwIfFatal(t);
        arbiter.emitError(t);
      }
    });
  }
}

以異步為例, 如果簡(jiǎn)單些, 可以如下

        Observable.create(new Observable.OnSubscribe<T>() {
            @Override
            public void call(Subscriber<T> subscriber) {
                call.enqueue(new Callback() {
                    @Override
                    public void onResponse(Call call, Response response) {
                        subscriber.onNext(response);
                    }

                    @Override
                    public void onFailure(Call call, Throwable t) {
                        subscriber.onError(t);
                    }
                });
            }
        });

到這里, 我們就可以回答問(wèn)題2了.
Retrofit通過(guò)動(dòng)態(tài)代理實(shí)現(xiàn)了接口中的方法, 在方法的最后, 使用了RxJavaCallAdapter#adapt方法來(lái)獲取結(jié)果, 而RxJavaCallAdapter#adapt做的也就是通過(guò)Observable.create創(chuàng)建Observable, 在調(diào)用OkHttpCall#enqueue方法拿到返回的結(jié)果后, 通過(guò)Observable發(fā)射出去, 生成Observable的數(shù)據(jù)流. 這樣就把生成的結(jié)果轉(zhuǎn)成了Observable.

在上面的異步方法中, 我們實(shí)際上通過(guò)retrofit2.Call#enqueue來(lái)獲取請(qǐng)求結(jié)果, 而這里的Call, 實(shí)際上是OkHttpCall, 所以, 我們來(lái)看下OkHttpCall#enqueue

OkHttpCall

OkHttpCall中有OkHttpCall#enqueue和OkHttpCall#execute, 分別對(duì)應(yīng)異步方法和同步方法
我們這里只說(shuō)OkHttpCall#enqueue

OkHttpCall#enqueue

    //如果callback為空, 拋出異常
    checkNotNull(callback, "callback == null");
    //...檢查各個(gè)參數(shù)
    //這里, 才是真正的調(diào)用了Okhttp的enqueue方法
    //調(diào)用OkHttp的enqueue異步方法, 獲取結(jié)果
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
        Response<T> response;
        try {
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }

        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        callFailure(e);
      }

      private void callFailure(Throwable e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
    });
  Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    //...
     //解析返回結(jié)果
    //這里也是問(wèn)題3的關(guān)鍵
    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
        //解析結(jié)果
        //泛型解析
        //這里跟我們創(chuàng)建Retrofit的時(shí)候通過(guò)addConverterFactory(GsonConverterFactory.create(gson)對(duì)應(yīng)
       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;
    }
  }

所以, 問(wèn)題3就是, 在OkHttpCall中, 拿到返回結(jié)果后, 將結(jié)果交給創(chuàng)建Retrofit的時(shí)候通過(guò)addConverterFactory(GsonConverterFactory.create(gson)生成的對(duì)應(yīng)的GsonConvert, 轉(zhuǎn)成對(duì)應(yīng)的對(duì)象

重新梳理

這里, 我們回國(guó)頭來(lái)重新看

 public <T> T create(final Class<T> service) {
    //...
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {

          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            //...

            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.adapt(okHttpCall);
          }
        });
  }
  1. 首先通過(guò)動(dòng)態(tài)代理, 生成對(duì)應(yīng)接口的實(shí)現(xiàn)類(lèi). 調(diào)用接口中的方法時(shí), 執(zhí)行動(dòng)態(tài)代理的invoke方法
  2. ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);
    方法, 獲取接口中方法的信息(方法返回值類(lèi)型/注解信息/參數(shù)類(lèi)型/參數(shù)注解等)
  3. 創(chuàng)建OkHttpCall(封裝Okttp中的Call為OkHttpCall)
  4. 執(zhí)行CallAdapter#adapter(這里的CallAdapter實(shí)際為RxJavaCallAdapter), 在RxJavaCallAdapter#adapter中執(zhí)行OkHttpCall#enqueue(以異步為例)執(zhí)行網(wǎng)絡(luò)請(qǐng)求, 并用Observable將結(jié)果發(fā)射出去成為Observable
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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