Retrofit原理分析

創(chuàng)建Retrofit實例

 new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();

  • 先看一下Retrofit的實例化
 new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();

這個就是配置一下baseUrl,轉(zhuǎn)換工程,然后設(shè)置到Retrofit這個創(chuàng)建出來的實例對象(源碼如下)

//baseURL
public Builder baseUrl(String baseUrl) {
      checkNotNull(baseUrl, "baseUrl == null");
      return baseUrl(HttpUrl.get(baseUrl));
    }
 public Builder baseUrl(HttpUrl baseUrl) {
      checkNotNull(baseUrl, "baseUrl == null");
      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;
    }

這樣就給retrofit的baseUrl賦值了,剩下的addConverterFactory,callAdapterFactory就不再貼源碼了

然后通過Retrofit.Build()...build()生成Retrofit實例

 public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories = new ArrayList<>(
          1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

      // Add the built-in converter factory first. This prevents overriding its behavior but also
      // ensures correct behavior when using converters that consume all types.
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);
      converterFactories.addAll(platform.defaultConverterFactories());

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

這個build()方法就是給Retrofit裝備數(shù)據(jù),然后生成Retrofit(由于每次對象都是new出來的所以我們用單利的設(shè)計模式,或者自己去做緩存啥的,保證唯一就行了)

到目前為止Retrofit的創(chuàng)建已經(jīng)完成了;這兒使用的是Builder設(shè)計模式

生成對應(yīng)的service(其實不是我們寫的Service的類,而是動態(tài)代理生成的他的子類)

retrofit.create(ServiceClass.class)
  • Retrofit的create源碼
public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(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);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }

我們看到生成service不再是我們的service,而是動態(tài)代理生成的對象(具體的話看一下動態(tài)代理的原理就知道了)


retofit_pic1.png
  • 然后會執(zhí)行到loadServerMethod方法
  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;
  }

先取緩存(ConCurrentHasMap-線程安全的)ServiceMethod,如果沒有就生成一個新的ServiceMethod(這兒就是我們?yōu)槭裁碦etrofit要進(jìn)行單利模式了)

  • ServiceMethod.parseAnnotations()生成新的ServiceMethod
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);
  }

先通過RequestFactory.parseAnnotations來進(jìn)行解析這個方法,生成RequestFactory

static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    return new Builder(retrofit, method).build();
  }
  
RequestFactory build() {
    //就是方法注解解析(GET,POST等),然后配置參數(shù)(httpMethod,hasBody,relativeUrl,relativeUrlParamNames)
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }
        ...省略一些代碼
        //參數(shù)注解解析(QUERY,BODY等)
      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
        parameterHandlers[p] =
            parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
      }
  ...省略一些代碼
      return new RequestFactory(this);
    }
  • 方法注解解析自己去看一下源碼就明白了沒什么,就是解析,然后裝配裝備參數(shù)
private void parseMethodAnnotation(Annotation annotation) {
    //判斷是哪個注解,然后配置對應(yīng)的參數(shù),
      if (annotation instanceof DELETE) {
        parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
      }
        ...省略
    }
    
  • 參數(shù)的注解解析
 private @Nullable ParameterHandler<?> parseParameter(
        int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) {
      ParameterHandler<?> result = null;
      if (annotations != null) {
        for (Annotation annotation : annotations) {
          ParameterHandler<?> annotationAction =
              parseParameterAnnotation(p, parameterType, annotations, annotation);
        ...省略
        }
      }

    }
    //分析一種注解Query
      @Nullable
 private ParameterHandler<?> parseParameterAnnotation( int p, Type type, Annotation[] annotations, Annotation annotation) {
   ...省略
   else if (annotation instanceof Query) {
               validateResolvableType(p, type);
               Query query = (Query) annotation;
               String name = query.value();
               boolean encoded = query.encoded();
       
               Class<?> rawParameterType = Utils.getRawType(type);
               gotQuery = true;
               if (Iterable.class.isAssignableFrom(rawParameterType)) {
                 if (!(type instanceof ParameterizedType)) {
                   throw parameterError(method, p, rawParameterType.getSimpleName()
                       + " must include generic type (e.g., "
                       + rawParameterType.getSimpleName()
                       + "<String>)");
                 }
                 ParameterizedType parameterizedType = (ParameterizedType) type;
                 Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
                 Converter<?, String> converter =
                     retrofit.stringConverter(iterableType, annotations);
                 return new ParameterHandler.Query<>(name, converter, encoded).iterable();
               } else if (rawParameterType.isArray()) {
                 Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
                 //retrofit.stringConverter轉(zhuǎn)化成Converter,如果你使用的是Query然后參數(shù)類型是自己定義的Bean的話,這個時候就需要自己去定義一下stringConverter
                 //因為Android里面常用的GsonConverter是沒有重寫這個方法的,這樣是傳過去(應(yīng)用地址的值)是不對的
                 Converter<?, String> converter =
                     retrofit.stringConverter(arrayComponentType, annotations);
                 return new ParameterHandler.Query<>(name, converter, encoded).array();
               } else {
                 Converter<?, String> converter =
                     retrofit.stringConverter(type, annotations);
                 return new ParameterHandler.Query<>(name, converter, encoded);
               }
       
             }
   ...省略
 }
  
   public <T> Converter<T, String> stringConverter(Type type, Annotation[] annotations) {
     checkNotNull(type, "type == null");
     checkNotNull(annotations, "annotations == null");
     //如果說我們給的convterFactory沒有重寫stringConverter的話就會返回一個BuiltInConverters.ToStringConverter.INSTANCE
     for (int i = 0, count = converterFactories.size(); i < count; i++) {
       Converter<?, String> converter =
           converterFactories.get(i).stringConverter(type, annotations, this);
       if (converter != null) {
         //noinspection unchecked
         return (Converter<T, String>) converter;
       }
     }
 
     // Nothing matched. Resort to default converter which just calls toString().
     //noinspection unchecked
     return (Converter<T, String>) BuiltInConverters.ToStringConverter.INSTANCE;
   }
   
   static final class ToStringConverter implements Converter<Object, String> {
       static final ToStringConverter INSTANCE = new ToStringConverter();
        //就是一個toString,所以對于引用的數(shù)據(jù)類型我們要進(jìn)行傳遞的話,我們放在query或者path里面的話就要去添加一個ConverterFactory(重寫里面的stringConverter)
       @Override public String convert(Object value) {
         return value.toString();
       }
     }
     
  • 上面我們值分析了一種注解Query(stringConverter轉(zhuǎn)換的),而如果是Body的話使用的是requestConverter,這里皆不貼源碼了,需要了解的自己去看吧

  • 最后生成一個RequestFactory實例(作用:解析注解(方法上面的注解,和參數(shù)上面的注解),配置對應(yīng)的請求參數(shù))

  • 接下來看ServiceMethod的生成過程,在ServiceMethod.parseAnnotations()方法里面會執(zhí)行HttpServiceMethod.parseAnnotations()來生成ServiceMethod對象

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

   ...省略
   //獲取Retrofit的CallAdapter
    CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
    Type responseType = callAdapter.responseType();
    ...省略
    //獲取Retrofit的ConverterFactory里面的responseConverter
    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

    //獲取Retrofit的callFactory(也就是我們設(shè)置的client)
    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    //生成對應(yīng)的ServiceMethod
    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);
    }
  }

到目前為止我們的ServiceMethod創(chuàng)建完了,然后我們看一種ServerMethod--CallAdapted

在動態(tài)代理里面會執(zhí)行ServiceMethod的invoke方法,也就是HttpServiceMethod的invoke->CallAdapted.adapt方法->callAdapter.adapt方法

//HttpServiceMethod的invoke
 @Override final @Nullable ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
  }
  
 //CallAdapted.adapt
 @Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
       return callAdapter.adapt(call);
     }
 //callAdapter.adapt方法(這兒是DefaultCallAdapterFactory)
  return new CallAdapter<Object, Call<?>>() {
       @Override public Type responseType() {
         return responseType;
       }
 
       @Override public Call<Object> adapt(Call<Object> call) {
           //如果沒有線程的話就直接返回這個call,有的話就將call封裝到線程里面
         return executor == null
             ? call
             : new ExecutorCallbackCall<>(executor, call);
       }
     };

callAdapter.adapt(call)--這個call就是OkHttpCall

  • 然后執(zhí)行方法了
//這是kotlin語法
val weatherDetail = weatherService.weatherDetail("101030100")
//            serviceCallCache.add(weatherDetail)
            weatherDetail.enqueue(object :Callback<WeatherBean>{
                override fun onFailure(call: Call<WeatherBean>, t: Throwable) {

                }

                override fun onResponse(call: Call<WeatherBean>, response: Response<WeatherBean>) {
                    textView.text=response.body()?.data?.wendu
                }
            })

然后執(zhí)行OkHttpCall的enqueue()方法

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

    okhttp3.Call call;
    Throwable failure;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      call = rawCall;
      failure = creationFailure;
      if (call == null && failure == null) {
        try {
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          throwIfFatal(t);
          failure = creationFailure = t;
        }
      }
    }

    if (failure != null) {
      callback.onFailure(this, failure);
      return;
    }

    if (canceled) {
      call.cancel();
    }
    //執(zhí)行Okhttp的enqueue()然后進(jìn)行回調(diào)
    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) {
          throwIfFatal(e);
          callFailure(e);
          return;
        }

        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          throwIfFatal(t);
          t.printStackTrace(); // TODO this is not great
        }
      }

      @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) {
          throwIfFatal(t);
          t.printStackTrace(); // TODO this is not great
        }
      }
    });
  }

我們看到最終執(zhí)行的是okHttp的enqueue()然后進(jìn)行回調(diào)

  • 到這兒源碼就分析完了,有沒有一個大題的印象呢

總結(jié)

  • 先創(chuàng)建Retrofit;通過Retrofit.Builder().build()的方法創(chuàng)建,你可以添加自己的converterFactory,callAdapterFactory,callFactory(client)
  • 通過動態(tài)代理創(chuàng)建執(zhí)行Call<Response>

1,指通過Retrofit.crete()

2,判斷緩存有沒有有的話直接執(zhí)行ServiceMethod的invoke方法

3,沒有緩存通過Retrofit.loadServiceMethod創(chuàng)建ServiceMethod

(1)先創(chuàng)建RequestFactory(解析注解,裝配對應(yīng)的請求參數(shù))
(2)在通過HttpServiceMethod.parseAnnotations生成對應(yīng)的ServiceMethod(里面會裝配callAdapter,callFactory,requestFactory,responseConverter)

4,執(zhí)行invoke生成call

(1) 執(zhí)行的是HttpServiceMethod.invoker->CallAdapted.adapt->CompletableFutureCallAdapterFactory.adapt方法返回call

5 ,執(zhí)行enqueue實際上是執(zhí)行的OkHttp的enqueue方法,然后進(jìn)行回調(diào)

如有錯誤請在下方留言,謝謝您的支持!

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

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

  • Retrofit 是目前作為網(wǎng)絡(luò)請求的主流框架,使用起來很方便,僅需在接口中定義方法,打上注解,而且和 Rxjav...
    Kip_Salens閱讀 684評論 0 3
  • 一,前言 Retrofit其實是將OKhttp封裝起來,和volley一樣。那解析Retrofit其實就是解析它如...
    求閑居士閱讀 1,462評論 2 5
  • 前言 注解式的框架非?;?,注解以其輕量,簡潔等特性被人們所喜愛者,關(guān)鍵是它解藕。網(wǎng)絡(luò)請求的框架非常多,比較受歡迎的...
    薩達(dá)哈魯醬閱讀 628評論 0 5
  • retrofit 源碼分析 retrofit 源碼分析源碼執(zhí)行流程new Retrofit.Builder().b...
    nightSin閱讀 460評論 0 1
  • 安卓開發(fā)領(lǐng)域中,很多重要的問題都有很好的開源解決方案,例如Square公司提供網(wǎng)絡(luò)請求 OkHttp , Retr...
    aaron688閱讀 1,994評論 1 20

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