美文网首页
retrofit源码分析

retrofit源码分析

作者: michael_2f73 | 来源:发表于2018-05-12 20:27 被阅读0次

    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<Converter.Factory> converterFactories = new ArrayList<>();
        private final List<CallAdapter.Factory> 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<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
          callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
    
          // Make a defensive copy of the converters.
          List<Converter.Factory> 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<T, R> {
        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<String> relativeUrlParamNames;
        ParameterHandler<?>[] parameterHandlers;
        Converter<ResponseBody, T> responseConverter;
        CallAdapter<T, R> 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<R, T> {
      /**
       * 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<Repo>} is {@code Repo}. This type
       * is used to prepare the {@code call} passed to {@code #adapt}.
       * <p>
       * 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}.
       * <p>
       * For example, given an instance for a hypothetical utility, {@code Async}, this instance would
       * return a new {@code Async<R>} which invoked {@code call} when run.
       * <pre><code>
       * &#64;Override
       * public &lt;R&gt; Async&lt;R&gt; adapt(final Call&lt;R&gt; call) {
       *   return Async.create(new Callable&lt;Response&lt;R&gt;&gt;() {
       *     &#64;Override
       *     public Response&lt;R&gt; call() throws Exception {
       *       return call.execute();
       *     }
       *   });
       * }
       * </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);
    
        /**
         * Extract the upper bound of the generic parameter at {@code index} from {@code type}. For
         * example, index 1 of {@code Map<String, ? extends Runnable>} 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<? extends Runnable>} returns {@code List.class}.
         */
        protected static Class<?> getRawType(Type type) {
          return Utils.getRawType(type);
        }
      }
    }
    
    

    代理模式

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

    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();
    
              @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<Object, Object> serviceMethod =
                    (ServiceMethod<Object, Object>) loadServiceMethod(method);
                OkHttpCall<Object> 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<Object, Call<?>>() {
          @Override public Type responseType() {
            return responseType;
          }
    
          @Override public Call<Object> adapt(Call<Object> call) {
            return new ExecutorCallbackCall<>(callbackExecutor, call);
          }
        };
      }
    

    装饰器模式

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

    static final class ExecutorCallbackCall<T> implements Call<T> {
        final Executor callbackExecutor;
        final Call<T> delegate;
    
        ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
          this.callbackExecutor = callbackExecutor;
          this.delegate = delegate;
        }
    

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

    final class OkHttpCall<T> implements Call<T> {
      private final ServiceMethod<T, ?> serviceMethod;
      private final @Nullable Object[] args;
    

    相关文章

      网友评论

          本文标题:retrofit源码分析

          本文链接:https://www.haomeiwen.com/subject/guyhdftx.html