Retrofit_2.5.0源碼分析

Retrofit_2.5.0源碼分析

基於Retrofit:3.12.0:github.com/square/retr…java

RTFSC

Read The Fucking Source Codegit

流程分析

  1. 用戶層面調用形式:
@NonNull
protected Retrofit.Builder createBuilder() {
    return new Retrofit.Builder().baseUrl(apiBaseUrl())
        .addConverterFactory(GsonConverterFactory.create(GsonUtils.getGson()))
        .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
        .client(okHttpClient());
    }

//原始call形式
Call api1=Retrofit#create(final Class<T> service).api()
api1.enqueue(Callback<T>)

//Rxjava形式
Obserable api2=Retrofit#create(final Class<T> service).api()
api2.subscibe{T t}

複製代碼
  1. Retrofit#create(final Class service):Retrofit典型的面向接口編程入口。傳遞進來咱們定義的API(接口形式)。能夠明顯看出,首先檢測傳遞進來的是不是接口,不然直接拋異常:throw new IllegalArgumentException("API declarations must be interfaces.")。接着執行是否提早初始化緩存該接口中全部的API方法。即便咱們沒有看下面的代碼,也能夠猜想出會和下面的方法有部分邏輯重合,由於"提早"初始化。先跳過提早初始化這一塊邏輯,由於是個性化業務。直接看重點動態代理。注意:InvocationHandler#invoke的返回值就是咱們定義的API的返回:Call或者Obserable,因此loadServiceMethod(method).invoke(args != null ? args : emptyArgs)=>ServiceMethod#invoke的返回值也就是Call或者Obserable,後面分析會用到。
//Retrofit
public <T> T create(final Class<T> service) {
    //檢測service是不是接口,不是直接拋異常
    Utils.validateServiceInterface(service);
    //是否提早遍歷緩存service中全部的接口
    if (validateEagerly) {
      eagerlyValidateMethods(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 {
            //其它輔助代碼...
            //核心入口:返回值就是咱們定義的API的返回值
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }
複製代碼
  1. 動態代理,單獨拿出來介紹一下。loader:代理對象的類加載器;interfaces代理對象數組;InvocationHandler#invoke:proxy代理對象的引用;method:接口中對應的方法;args:方法中的參數;返回值:Object就是method對應的返回值。
Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}                                          

複製代碼
  1. InvocationHandler#invoke=>Retrofit#loadServiceMethod#invoke=>ServiceMethod#invoke:首先根據method做爲key檢查是否在緩存中,存在直接返回;不然ServiceMethod#parseAnnotations去根據方法解析。進行下面分析前,咱們回想一下,這裏的"method"指的是什麼?對的,就是咱們在接口中定義的API,ServiceMethod.parseAnnotations(this, method)是核心,那會作些什麼?根據名字能夠猜想:解析參數、註解、返回值...繼續看,是否和咱們猜想一致。
//Retrofit
   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;
  }
複製代碼
  1. Retrofit#loadServiceMethod=>ServiceMethod#parseAnnotations(retrofit, method)=>RequestFactory.parseAnnotations=>RequestFactory#build():目的:解析方法的註解、參數註解、以及參數。這裏會調用RequestFactory.parseAnnotations(retrofit, method)生成RequestFactory對象。parseAnnotations根據下面的RequestFactory#Builder能夠看出主要遍歷方法註解和參數註解存到RequestFactory中,方便後續使用。
abstract class ServiceMethod<T> {
 static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
   //根據method解析method參數、註解、返回值生成RequestFactory對象
   RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

   //這裏先不看,下面再分析...
   return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
 }
}
複製代碼
RequestFactory#Builder
RequestFactory build() {
      //解析方法上面的註解    
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }

      //...
        
      //解析方法參數中的註解        
      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        parameterHandlers[p] = parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p]);
      }

      //...

      return new RequestFactory(this);
    }
    
    RequestFactory#Builder
    private void parseMethodAnnotation(Annotation annotation) {
      //解析方法上的註解,不一樣的類型請求
      if (annotation instanceof DELETE) {
        parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
      } else if (annotation instanceof GET) {
        parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
      } ...其它類型的請求
    }
    
    //解析參數註解,要遍歷每一個參數,由於每一個參數均可能有註解
    private ParameterHandler<?> parseParameter(
        int p, Type parameterType, @Nullable Annotation[] annotations) {
      ParameterHandler<?> result = null;
      if (annotations != null) {
        for (Annotation annotation : annotations) {
          ParameterHandler<?> annotationAction =
              parseParameterAnnotation(p, parameterType, annotations, annotation);

          ...
      }
     ...
      return result;
    }
    
    //解析參數註解:賊長的遍歷解析,寫框架不只須要架構經驗,仍是一個體力活
    @Nullable
    private ParameterHandler<?> parseParameterAnnotation(
        int p, Type type, Annotation[] annotations, Annotation annotation) {
      if (annotation instanceof Url) {
        ...
      } else if (annotation instanceof Path) {
        ...
      } else if (annotation instanceof Query) {
        ...
      } else ...

      return null; // Not a Retrofit annotation.
    }

複製代碼
  1. ServiceMethod#parseAnnotations=>HttpServiceMethod#parseAnnotations=>HttpServiceMethod#createCallAdapter:目的:解析方法的返回值,確認CallAdapter。
#ServiceMethod
abstract class ServiceMethod<T> {
  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    //上一步有分析
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

    //...
    
    //入口,生成HttpServiceMethod對象
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }


}
  
複製代碼
//HttpServiceMethod#parseAnnotations
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    //重點:入口
    CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
    
    //...

    //根據callAdapter構建Converter包裝類
    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    //構建HttpServiceMethod
    return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
  }
  
  //HttpServiceMethod
  private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
      Retrofit retrofit, Method method) {
      Type returnType = method.getGenericReturnType();
      //根據返回值獲取CallAdapter
      return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
  }

複製代碼
  1. HttpServiceMethod#createCallAdapter=>Retrofit#callAdapter:目的:遍歷callAdapterFactories尋找CallAdapter,只要不爲null就符合條件。
//Retrofit
 public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }
  
  // Retrofit
  public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    //...
    
    //遍歷callAdapterFactories,這個是咱們設置retrofit的時候Retrofit#Builder#addCallAdapterFactory
    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;
      }
    }

   //...
  }
複製代碼
  1. InvocationHandler#invoke=>ServiceMethod#invoke=>HttpServiceMethod#invokeCallAdapter#adapt=>RxJava2CallAdapter#adapt:目的:獲取返回值,回溯到動態代理,結束。下面是RxJava2CallAdapter的一個實現,咱們能夠看出返回值就是相似Obserable這種形式。
//ServiceMethod
abstract class ServiceMethod<T> {
  //動態代理最後調用的方法
  abstract T invoke(Object[] args);
}
複製代碼
final class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
  //最終動態代理調用的方法        
  @Override ReturnT invoke(Object[] args) {
    return callAdapter.adapt(
        new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
  }
}

複製代碼
//RxJava2CallAdapter,這是一個CallAdapter其中的一個實現
final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {
 
  @Override public Object adapt(Call<R> call) {
    //這裏取作真正的調用
    Observable<Response<R>> responseObservable = isAsync
        ? new CallEnqueueObservable<>(call)
        : new CallExecuteObservable<>(call);

    Observable<?> observable;
    if (isResult) {
      observable = new ResultObservable<>(responseObservable);
    } else if (isBody) {
      observable = new BodyObservable<>(responseObservable);
    } else {
      observable = responseObservable;
    }

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

    if (isFlowable) {
      return observable.toFlowable(BackpressureStrategy.LATEST);
    }
    if (isSingle) {
      return observable.singleOrError();
    }
    if (isMaybe) {
      return observable.singleElement();
    }
    if (isCompletable) {
      return observable.ignoreElements();
    }
    return RxJavaPlugins.onAssembly(observable);
  }
}


final class CallEnqueueObservable<T> extends Observable<Response<T>> {
  private final Call<T> originalCall;

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

  @Override protected void subscribeActual(Observer<? super Response<T>> observer) {
    // Since Call is a one-shot type, clone it for each new observer.
    Call<T> call = originalCall.clone();
    CallCallback<T> callback = new CallCallback<>(call, observer);
    observer.onSubscribe(callback);
    if (!callback.isDisposed()) {
      //最後的call API    
      call.enqueue(callback);
    }
  }


複製代碼

參考

  1. github.com/square/retr…
  2. www.jianshu.com/p/cb444f49a…
相關文章
相關標籤/搜索