Retrofit中關於CallAdapter使用的設計模式分析


Retrofit作爲Square公司出品非常受歡迎的的http網絡請求框架,使用了非常多的設計模式,非常值得我們學習。今天我就給大家分析一下其中CallAdapter中使用到的設計模式。

CallAdapter的使用

CallAdapterRetrofit中的是通過Retrofit.Builder中的addCallAdapterFactory(CallAdapter.Factory factory)方法添加的CallAdapter.Factoy,直接看使用代碼:

	public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      callAdapterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }

然後在需要CallAdapter的時候,通過CallAdapter.Factoyget()方法來獲取對象CallAdapter

public interface CallAdapter<R, T> {
  ......

  /**
   * Returns an instance of {@code T} which delegates to {@code call}.
   * </code></pre>
   */
  T adapt(Call<R> call);

  /**
   * Creates {@link CallAdapter} instances based on the return type of {@linkplain
   * Retrofit#create(Class) the service interface} methods.
   */
  abstract class Factory {
    /**
     * Returns a call adapter for interface methods that return {@code returnType}, or null if it
     * cannot be handled by this factory.
     */
    public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
        Retrofit retrofit);

    .......
  }
}

CallAdapter中的適配器模式

適配器模式(Adapter Pattern):將一個接口轉換成客戶希望的另一個接口,使接口不兼容的那些類可以一起工作,其別名爲包裝器(Wrapper)。適配器模式既可以作爲類結構型模式,也可以作爲對象結構型模式。
CallAdapter名字就包含適配器Adapter,也算“人如其名”,使用到了適配器模式。我們來看下CallAdapter接口中的adapt()方法:

public interface CallAdapter<R, T> {
  ......

  /**
   * Returns an instance of {@code T} which delegates to {@code call}.
   * </code></pre>
   */
  T adapt(Call<R> call);
}

就是將一個Call<R>對象轉換成一個泛型T所代表的對象,簡單清晰明瞭。

CallAdapter中的工廠方法模式

適配器模式(Adapter Pattern):工廠方法模式將生成具體產品的任務分發給具體的產品工廠。
CallAdapter的生成都交給其工廠實現類,比如RxJava2CallAdapter的工廠類RxJava2CallAdapterFactory


public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {
    .......

  @Override public @Nullable CallAdapter<?, ?> get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
    Class<?> rawType = getRawType(returnType);

    if (rawType == Completable.class) {
      // Completable is not parameterized (which is what the rest of this method deals with) so it
      // can only be created with a single configuration.
      return new RxJava2CallAdapter(Void.class, scheduler, isAsync, false, true, false, false,
          false, true);
    }

    .......
    
    if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
      return null;
    }

    .......

    return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
        isSingle, isMaybe, false);
  }
}

使用配置的時候也都是配置的CallAdapter的工廠類。

Retrofit使用策略模式匹配合適的CallAdapter

**策略模式(Strategy):**定義了一組算法,將每個算法都封裝起來,並且使它們之間可以互換。
前面在CallAdapter的使用中我們看到可以添加多個CallAdapter.Factory對象,相當於我們封裝了多個不同的適配算法CallAdapter.adapt()。那麼接下來我們來看看源碼中是不是真的在其中匹配了某個CallAdapterCallAdapter對象的生成和調用其實實在HttpServerMethod對象的parseAnnotations()方法裏觸發的,parseAnnotations()->createCallAdapter()

abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
  /**
   * Inspects the annotations on an interface method to construct a reusable service method that
   * speaks HTTP. This requires potentially-expensive reflection so it is best to build each service
   * method only once and reuse it.
   */
  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
      .......
      
    if (isKotlinSuspendFunction) {
      ......

    CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
    Type responseType = callAdapter.responseType();
    ......
    }
    ......
  }

  private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
      Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
    try {
      //noinspection unchecked
      return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
    } catch (RuntimeException e) { 
      .......
    }
  }
 }

然後回到Retrofit對象的callAdapter() -> nextCallAdapter()

public final class Retrofit {
  ......
  
  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;
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }
    ......
  }
 ......
 }

在的nextCallAdapter()方法中,根據返回值retrunType類型遍歷調用CallAdapter.Factoryget()方法,如果返回的CallAdapter對象部位null則直接返回改對象,說明CallAdapter.Factoryget()應該是根據retrunType確定是否返回CallAdapter對象(是否選擇該種策略)。下面看兩種默認實現的CallAdapter.Factory

  • RxJava2CallAdapterFactory
public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {
  ......
  
  @Override public @Nullable CallAdapter<?, ?> get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
    Class<?> rawType = getRawType(returnType);

    ......
    if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
      return null;
    }
    .......
  }
}
  • DefaultCallAdapterFactory
public final class DefaultCallAdapterFactoryextends CallAdapter.Factory {
  ......
  
  @Override public @Nullable CallAdapter<?, ?> get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    .......
  }
}

總結

由於本篇主要分析設計模式的使用流程,所以去掉了大部分的代碼,只保留了最核心的,與設計模式有關的代碼,力求最簡單的方式呈現設計模式的使用流程。文中提到了兩種設計模式的使用:

  • 適配器模式:主要將Call對象轉換成我們想要的目標對象,比如RxJavaObservable
  • 策略模式:主要用於在我們配置好的一些列適配器工廠列表中匹配我們需要的適配器工廠

由於個人水平可能有限,如果上述博文有不正確的地方,歡迎大家指正

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章