Retrofit+Okhttp源碼鏈路(一)

一、retrofit和okhttp初始化配置

1.Retrofit配置

  • client:網(wǎng)絡(luò)請(qǐng)求引擎
  • addCallAdapterFactory:響應(yīng)網(wǎng)絡(luò)數(shù)據(jù)后,包裝數(shù)據(jù)后期望類型,可加多個(gè)
  • addConverterFactory:數(shù)據(jù)解析轉(zhuǎn)換類型,常用:GsonConverterFactory.create()
  • baseUrl:主要url必須以 "/" 結(jié)尾,格式有強(qiáng)校驗(yàn)

2.Okhttp配置
常規(guī)配置攔截器、網(wǎng)絡(luò)連接、讀寫超時(shí)不過多介紹,主要說明幾個(gè)實(shí)用的:

  • proxy:代理設(shè)置,Proxy.NO_PROXY設(shè)置該類型可以防止應(yīng)用被抓包
  • eventListener:監(jiān)聽網(wǎng)絡(luò)鏈路生命周期各個(gè)階段時(shí)間消化,可做為網(wǎng)絡(luò)數(shù)據(jù)監(jiān)聽使用
  • getDispatcher$okhttp().setMaxRequestsPerHost:設(shè)置單個(gè)域名最大請(qǐng)求數(shù)
  • connectionPool:自定義網(wǎng)絡(luò)連接復(fù)用池個(gè)數(shù)以及復(fù)用時(shí)長(zhǎng)
  • setDns$okhttp:自定義解析DNS

二、網(wǎng)絡(luò)請(qǐng)求發(fā)起

1.通過retrofit的實(shí)例調(diào)用create方法或者到service的實(shí)例,然后調(diào)用對(duì)應(yīng)方法。

public <T> T create(final Class<T> service) {
    validateServiceInterface(service);
    return (T)
        Proxy.newProxyInstance(
            service.getClassLoader(),
            new Class<?>[] {service},
            new InvocationHandler() {
              private final Platform platform = Platform.get();
              private final Object[] emptyArgs = new Object[0];

              @Override
              public @Nullable 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) {
                  return method.invoke(this, args);
                }
                args = args != null ? args : emptyArgs;
                return platform.isDefaultMethod(method)
                    ? platform.invokeDefaultMethod(method, service, proxy, args)
                    : loadServiceMethod(method).invoke(args);
              }
            });
  }

首先通過validateServiceInterface方法校驗(yàn)class泛型參數(shù)是否是interface,而且會(huì)校驗(yàn)是否是一個(gè)不為空定義的interface,必須是interface的原因是需要通過動(dòng)態(tài)代理去反射生成實(shí)例,動(dòng)態(tài)代理必須是interface(java的單繼承、多接口實(shí)現(xiàn))。

2.通過loadServiceMethod方法獲取一個(gè)HttpServiceMethod,該方法內(nèi)有一個(gè)復(fù)用邏輯。

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

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = ServiceMethod.parseAnnotations(this, method);
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

通過靜態(tài)方法parseAnnotations解析得到對(duì)應(yīng)的實(shí)例對(duì)象。

static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) {
      throw methodError(
          method,
          "Method return type must not include a type variable or wildcard: %s",
          returnType);
    }
    if (returnType == void.class) {
      throw methodError(method, "Service methods cannot return void.");
    }

    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

首先會(huì)通過method去構(gòu)建一個(gè)RequestFactory,然后去調(diào)用hasUnresolvableType校驗(yàn)方法是否有有效的返回值(因?yàn)橐粋€(gè)網(wǎng)絡(luò)請(qǐng)求發(fā)出必須有值給到響應(yīng)),最后去通過parseAnnotations方法構(gòu)建一個(gè)有效的ServiceMethod。
思考:RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
為什么不放在校驗(yàn)條件之后,如下述條件不成立,這個(gè)地方為無(wú)效創(chuàng)建。

static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
    boolean continuationWantsResponse = false;
    boolean continuationBodyNullable = false;

    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
    if (isKotlinSuspendFunction) {
      Type[] parameterTypes = method.getGenericParameterTypes();
      Type responseType =
          Utils.getParameterLowerBound(
              0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
      if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
        // Unwrap the actual body type from Response<T>.
        responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
        continuationWantsResponse = true;
      } else {
        // TODO figure out if type is nullable or not
        // Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)
        // Find the entry for method
        // Determine if return type is nullable or not
      }

      adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
      annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
    } else {
      adapterType = method.getGenericReturnType();
    }

    CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
    Type responseType = callAdapter.responseType();
    if (responseType == okhttp3.Response.class) {
      throw methodError(
          method,
          "'"
              + getRawType(responseType).getName()
              + "' is not a valid response body type. Did you mean ResponseBody?");
    }
    if (responseType == Response.class) {
      throw methodError(method, "Response must include generic type (e.g., Response<String>)");
    }
    // TODO support Unit for Kotlin?
    if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
      throw methodError(method, "HEAD method must use Void as response type.");
    }

    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    if (!isKotlinSuspendFunction) {
      return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
    } else if (continuationWantsResponse) {
      //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
      return (HttpServiceMethod<ResponseT, ReturnT>)
          new SuspendForResponse<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
    } else {
      //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
      return (HttpServiceMethod<ResponseT, ReturnT>)
          new SuspendForBody<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
              continuationBodyNullable);
    }
  }

這個(gè)方法整體執(zhí)行邏輯是先校驗(yàn)該方法是否kotlin的suspend得到對(duì)應(yīng)的adapterType,然后拿到方法的所有注解列表,去得到實(shí)際的CallAdapter。調(diào)用createCallAdapter去創(chuàng)建CallAdapter,然后會(huì)繼續(xù)調(diào)用retrofit的callAdapter->nextCallAdapter方法,繼續(xù)看代碼:

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

    int start = callAdapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }

該方法會(huì)先去校驗(yàn)是否有返回值和注解,然后會(huì)去在callAdapterFactories里邊找對(duì)應(yīng)callAdapter,看到這里callAdapterFactories里的callAdapter就和我們初始化retrofit中加的addCallAdapterFactory有關(guān)系了。最后就包裝生成一個(gè)ServiceMethod實(shí)例了。
再回到動(dòng)態(tài)方法里通過serviceMethod對(duì)象invoke方法去真正執(zhí)行網(wǎng)絡(luò)調(diào)用。
loadServiceMethod(method).invoke(args);

@Override
  final @Nullable ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
  }
最后編輯于
?著作權(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),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 一、前言二、源碼解析1、構(gòu)建Retrofit對(duì)象 1.1、Retrofit類的成員變量 1.2、Retrofi...
    huangLearn閱讀 682評(píng)論 0 1
  • 前言 之前講過了okhttp的超級(jí)概括的原理解析,okhttp以它優(yōu)秀的線程池設(shè)計(jì),任務(wù)隊(duì)列的分配和轉(zhuǎn)化以及基于責(zé)...
    Dex_閱讀 240評(píng)論 0 1
  • Retrofit2作為目前最火的網(wǎng)絡(luò)請(qǐng)求框架之一,它是一個(gè)由Square組織開發(fā)的可以在Android和java中...
    maoqitian閱讀 736評(píng)論 0 1
  • 本文概述Retrofit作為主流的網(wǎng)絡(luò)框架,采用注解和接口的方式封裝請(qǐng)求,使得調(diào)用過程變得優(yōu)雅又簡(jiǎn)潔,優(yōu)雅的背后肯...
    Horps閱讀 367評(píng)論 0 1
  • Retrofit的簡(jiǎn)單使用 1. 添加依賴 2. 創(chuàng)建一個(gè)interface作為Web Service的請(qǐng)求集合,...
    Hsicen閱讀 243評(píng)論 0 1

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