小言_互联网的博客

Retrofit中关于CallAdapter使用的设计模式分析

458人阅读  评论(0)


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所代表的对象,简单清晰明了。

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
  • 策略模式:主要用于在我们配置好的一些列适配器工厂列表中匹配我们需要的适配器工厂

由于个人水平可能有限,如果上述博文有不正确的地方,欢迎大家指正


转载:https://blog.csdn.net/OxuanO/article/details/106785282
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场