Retrofit2源碼學(xué)習(xí)之流程詳解

綜述

Retrofit到一個(gè)實(shí)際請(qǐng)求/響應(yīng)的過程包括

  • 創(chuàng)建ServiceMethod,調(diào)用ServiceMethod.build()
  • 調(diào)用OkHttpCall(ServiceMethod,args)創(chuàng)建OkHttpCall對(duì)象,
  • 調(diào)用 CallAdapter.adapt(okHttpCall)創(chuàng)建關(guān)聯(lián)執(zhí)行器Executor和Call的應(yīng)用層Call類,Android默認(rèn)為ExecutorCallbackCall

源碼研究

  • 創(chuàng)建ServiceMethod

ServiceMethod.build()

  public ServiceMethod build() {
      //通過Retrofit.nextCallAdapter獲取callAdapter,有自定義就用自定義,沒有就用默認(rèn)ExecutorCallAdapterFactory
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      //返回類型驗(yàn)證
      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?");
      }
      //通過Retrofit.nextResponseBodyConverter處理轉(zhuǎn)換異常,獲得自定義轉(zhuǎn)換器
      responseConverter = createResponseConverter();
      //解析自定義的注解成URL組件
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }

      //錯(cuò)誤處理
      ...
      //構(gòu)建參數(shù)替換的輔助數(shù)組parameterHandlers
      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        if (Utils.hasUnresolvableType(parameterType)) {
          throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
              parameterType);
        }

        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        if (parameterAnnotations == null) {
          throw parameterError(p, "No Retrofit annotation found.");
        }
        
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }
      //錯(cuò)誤處理
     ...
      return new ServiceMethod<>(this);
    }
  • 用戶調(diào)用enqueue方法發(fā)起異步請(qǐng)求

ExecutorCallbackCall.enqueue()

    @Override public void enqueue(final Callback<T> callback) {
      checkNotNull(callback, "callback == null");
      //調(diào)用OkhttpCall的enqueue方法,Executor執(zhí)行響應(yīng)結(jié)果
      delegate.enqueue(new Callback<T>() {
        
        }
      });
    }

OkHttpCall. enqueue

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

    okhttp3.Call call;
    Throwable failure;

    synchronized (this) {
          ...
          //這里創(chuàng)建請(qǐng)求報(bào)文獲得realCall
          call = rawCall = createRawCall();
           ...
    }
    //realCall發(fā)起異步請(qǐng)求
    call.enqueue(new okhttp3.Callback() {
           ...
          //轉(zhuǎn)換響應(yīng)報(bào)文
          response = parseResponse(rawResponse);
          ...
   
    });
  }

createRawCall

  private okhttp3.Call createRawCall() throws IOException {
    //創(chuàng)建request報(bào)文
    Request request = serviceMethod.toRequest(args);
    //獲得okhttp.realCall
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }

serviceMethod.toRequest(args)

  Request toRequest(@Nullable Object... args) throws IOException {
    RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
        contentType, hasBody, isFormEncoded, isMultipart);
    ...
    @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
    ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
    //根據(jù)先前的parameterHandlers進(jìn)行參數(shù)轉(zhuǎn)換
    for (int p = 0; p < argumentCount; p++) {
      handlers[p].apply(requestBuilder, args[p]);
    }
    //創(chuàng)建request報(bào)文
    return requestBuilder.build();
  }

parseResponse

 Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();
    //異常處理,200-299成功狀態(tài)碼,204和205沒有響應(yīng)body
   ...
      //serviceMethod.toResponse用戶轉(zhuǎn)換器轉(zhuǎn)換
      T body = serviceMethod.toResponse(catchingBody);
      return Response.success(body, rawResponse);

  }

總結(jié)

通過梳理大體了解的Retrofit的整體結(jié)構(gòu)和流程,當(dāng)然還有很多的細(xì)節(jié)沒有討論,需要時(shí)可以查看相應(yīng)的源碼。
Retrofit源碼本身并不復(fù)雜,但是Retrofit的架構(gòu)設(shè)計(jì),解耦所透露的架構(gòu)經(jīng)驗(yàn),思想,規(guī)范等是非常值得我們學(xué)習(xí)和參照設(shè)計(jì)的。

最后編輯于
?著作權(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)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 適配器模式上一篇文章我們已經(jīng)分析了Retrofit解析注解封裝進(jìn)ServiceMethod的流程,讀者在這里要記住...
    andcoder閱讀 781評(píng)論 0 2
  • 最近非常流行 Retrofit+RxJava+OkHttp 這一整套的網(wǎng)絡(luò)請(qǐng)求和異步操作的開源框架,從 Jake ...
    慌不要慌閱讀 2,032評(píng)論 1 7
  • Retrofit這個(gè)開源庫出來也有一定年頭了,記得之前還是在V1.0的版本的時(shí)候,之前在三月份也寫過一個(gè)Retro...
    lovejjfg閱讀 1,512評(píng)論 0 5
  • 一、什么是Retrofit A type-safe HTTP client for Android and Jav...
    andcoder閱讀 857評(píng)論 2 3
  • 好的開場(chǎng)白是成功的一半,很多演講高手都說,如果沒有一個(gè)好的開頭,想在整個(gè)演說過程中做到輕松、巧妙地與聽眾交流思想交...
    苗軒鳴閱讀 594評(píng)論 0 2

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