retrofit源码分析

Retrofit是square公司开发的网络请求框架,代码虽然不多,但是却应用到了非常多设计模模式,这里将从设计模式的角度一一分析,学习有些美的代码。

前言

在使用retrofit的时候,我们知道首先是通过Retrofit.Builder()生成一个Retrofit实例,接着调用retrofit.creat(api.class)得到一个直接可以用于请求的实例,比如默认的Call或者是使用了rxjava的Observable。
在大方向上我挑出两个最重要的类,Retrofit和ServiceMethod。
retrofit属于基础的用于构建类的类,其中包含生成类的类型是什么,基础url多少,使用什么请求网络(默认okhttp),怎么样转换请求回来的数据,这些是需要提前知道的,先需要告诉retrofit。
serviceMethod方法则是在运行中动态生成的(代码实际有做缓存),生成实际使用类时,即在retrofit.creat()方法中生成serviceMethod,serviceMethod构建时会传入retrofit,意思就是serviceMethod有类retrofit所有方法和属性了。通过serviceMethod将会解析出所有需要生成的类和方法。

接下来就从设计模式开始分析吧

建造者模式

建造者模式,一般用于生成类需要比较多参数,条件的情况下使用,retrofit的实例化就是通过Builder类来生成的,先构造出Builder类,最后调用Builder类的builder()方法。

Retrofit.Builder

public static final class Builder {
    private final Platform platform;
    private @Nullable okhttp3.Call.Factory callFactory;
    private HttpUrl baseUrl;
    private final List converterFactories = new ArrayList<>();
    private final List callAdapterFactories = new ArrayList<>();
    private @Nullable Executor callbackExecutor;
    private boolean validateEagerly;

    Builder(Platform platform) {
      this.platform = platform;
    }

    public Builder() {
      this(Platform.get());
    }

    Builder(Retrofit retrofit) {
      platform = Platform.get();
      callFactory = retrofit.callFactory;
      baseUrl = retrofit.baseUrl;

      converterFactories.addAll(retrofit.converterFactories);
      // Remove the default BuiltInConverters instance added by build().
      converterFactories.remove(0);

      callAdapterFactories.addAll(retrofit.callAdapterFactories);
      // Remove the default, platform-aware call adapter added by build().
      callAdapterFactories.remove(callAdapterFactories.size() - 1);

      callbackExecutor = retrofit.callbackExecutor;
      validateEagerly = retrofit.validateEagerly;
    }
    //......
    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 callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

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

      // 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);

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

ServiceMethod.Builder

static final class Builder {
    final Retrofit retrofit;
    final Method method;
    final Annotation[] methodAnnotations;
    final Annotation[][] parameterAnnotationsArray;
    final Type[] parameterTypes;

    Type responseType;
    boolean gotField;
    boolean gotPart;
    boolean gotBody;
    boolean gotPath;
    boolean gotQuery;
    boolean gotUrl;
    String httpMethod;
    boolean hasBody;
    boolean isFormEncoded;
    boolean isMultipart;
    String relativeUrl;
    Headers headers;
    MediaType contentType;
    Set relativeUrlParamNames;
    ParameterHandler[] parameterHandlers;
    Converter responseConverter;
    CallAdapter callAdapter;

    Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      this.methodAnnotations = method.getAnnotations();
      this.parameterTypes = method.getGenericParameterTypes();
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

    public ServiceMethod build() {
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }
      responseConverter = createResponseConverter();

      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }

      if (httpMethod == null) {
        throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
      }

      if (!hasBody) {
        if (isMultipart) {
          throw methodError(
              "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
        }
        if (isFormEncoded) {
          throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
              + "request body (e.g., @POST).");
        }
      }

      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        if (Utils.hasUnresolvableType(parameterType)) {
          throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
              parameterType);
        }

        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        if (parameterAnnotations == null) {
          throw parameterError(p, "No Retrofit annotation found.");
        }

        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }

      if (relativeUrl == null && !gotUrl) {
        throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
      }
      if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
        throw methodError("Non-body HTTP method cannot contain @Body.");
      }
      if (isFormEncoded && !gotField) {
        throw methodError("Form-encoded method must contain at least one @Field.");
      }
      if (isMultipart && !gotPart) {
        throw methodError("Multipart method must contain at least one @Part.");
      }

      return new ServiceMethod<>(this);
    }

工厂模式

工厂模式用得比较多,在生成CallAdapter时,使用了CallAdapterFactory;converterFacory,这里贴一下CallAdapterFactory的代码;

public interface CallAdapter {
  /**
   * Returns the value type that this adapter uses when converting the HTTP response body to a Java
   * object. For example, the response type for {@code Call} is {@code Repo}. This type
   * is used to prepare the {@code call} passed to {@code #adapt}.
   * 

* Note: This is typically not the same type as the {@code returnType} provided to this call * adapter's factory. */ Type responseType(); /** * Returns an instance of {@code T} which delegates to {@code call}. *

* For example, given an instance for a hypothetical utility, {@code Async}, this instance would * return a new {@code Async} which invoked {@code call} when run. *


   * @Override
   * public <R> Async<R> adapt(final Call<R> call) {
   *   return Async.create(new Callable<Response<R>>() {
   *     @Override
   *     public Response<R> call() throws Exception {
   *       return call.execute();
   *     }
   *   });
   * }
   * 
*/ T adapt(Call 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); /** * Extract the upper bound of the generic parameter at {@code index} from {@code type}. For * example, index 1 of {@code Map} returns {@code Runnable}. */ protected static Type getParameterUpperBound(int index, ParameterizedType type) { return Utils.getParameterUpperBound(index, type); } /** * Extract the raw class type from {@code type}. For example, the type representing * {@code List} returns {@code List.class}. */ protected static Class getRawType(Type type) { return Utils.getRawType(type); } } }

代理模式

生成我们使用的请求实例用的就是动态代理模式,这也是retrofit的精髓,使用动态代理只需要简单写一些接口,极大的简化了代码
这里贴一下关键代码

public  T create(final Class 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();

          @Override public 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);
            }
            ServiceMethod serviceMethod =
                (ServiceMethod) loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.adapt(okHttpCall);
          }
        });
  }

适配器模式

适配器模式上,用的地方是在callAdapter,将OkHttpCall转化成需要的类型,没有添加callAdapterFactory的retrofit,默认将使用ExecuterCallAdapterFactory,其中将适配成需要的Call。
这里贴一下默认的代码

 @Override
  public CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public Call adapt(Call call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }

装饰器模式

装饰器模式也是在默认的CallAdaterFactory生成的Call中有用到。

static final class ExecutorCallbackCall implements Call {
    final Executor callbackExecutor;
    final Call delegate;

    ExecutorCallbackCall(Executor callbackExecutor, Call delegate) {
      this.callbackExecutor = callbackExecutor;
      this.delegate = delegate;
    }

上面的delegate属于装饰器。
实际的Call为由serviceMethod生成的OKhttpCall中的Call

final class OkHttpCall implements Call {
  private final ServiceMethod serviceMethod;
  private final @Nullable Object[] args;

你可能感兴趣的:(retrofit源码分析)