Retrofit-源码分析

前言

前段时间在看基于Retrofit-2.5.0的源码,一个好的框架必定集合了很多知识点,合理的运用这些基础的知识,才能累积起来一个优秀的作品。为了学习这个框架,重新看了反射注解,相关设计模式等知识,梳理了Retrofit的相关流程和使用方法。这里将做一个总结,如有纰漏之处,万望指出。如果有幸你看到了这篇博客,学习之余还是得多思考,并且对于这个框架前辈都是一步一步调试得出其整个流程,你也需要多调试。

如何发起一个请求

看过Retrofit的相信都知道其底层请求网络都使用的是OkHttp,这里我们首先得知道OkHttp发起一个请求都需要哪些东西,这些东西在Retrofit中是怎么生成和封装的。
首先这里我们看一个异步的OkHttp请求,这里可以看到发起一个请求需要3个元素,从后往前看

  1. Call:用于发起请求
  2. OkHttpClient:至少表面上看是使用Request创建了一个Call
  3. Request:设置参数以及各种请求所需要的元素

那么对应到Retrofit中,其必定也是要构造这些去发起请求。那么我们就看其是怎么生成这些,并进行封装的。

String url = "http://wwww.baidu.com";
OkHttpClient okHttpClient = new OkHttpClient();
final Request request = new Request.Builder()
        .url(url)
        .get()//默认就是GET请求,可以不写
        .build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        Log.d(TAG, "onFailure: ");
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        Log.d(TAG, "onResponse: " + response.body().string());
    }
});

Retrofit请求流程

对于发起一个Retrofit的请求实在是过于简单,前面Retroft-简单封装里面有其简单的封装和使用。
对于学习Retrofit框架,首先在大局上要有一个观念。对其大的脉络有大致的了解,细枝末节想看的时候再深入去看。在看下面的内容前,我们先对Retrofit的使用流程和巧妙之处做一个介绍:

在这里插入图片描述
首先在网上盗一张图,上面流程可以分为2部分,一部分是各种创建网络请求的部分,一直到使用适配器模式的CallAdapter,二部分是具体适配3种CallAdapter以及其各自逻辑处理,这里可以看到适配的常规的AndroidCallAdapter,java8CallAdapter,以及非常普及的RxJavaCallAdapter。对于Retrofit来说,其架构上用到很多设计模式,做到很好的扩展。在其中CallAdapter和Converter的设计非常巧妙。如果有看不懂的请看回头看这篇博客

再看Retrofit的创建以及初始化,创建Retrofit的时候主要是Retrofit.Builder()方法可以进行相关的设置,比如设置okHttpClient,以及添加addConverterFactory,用于数据请求后的解析。然后调用retrofit.create(Api.class)返回了一个事先定义好的用于请求的Api接口,而Api接口并没有具体的实现,这里的create方法返回Api用到了动态代理技术,而Api中onLogin方法返回一个装有News泛型的Call对象,那么就使用Call对象的enqueue方法就发起了请求;请求发起后,是由OkHttp做处理,返回Response,然后经过设置的Converter,将其转换成需要的数据对象进行返回
简单的使用中可以看到Retrofit框架中的相关类,那么我在这里将使用到的相关类都遇到后都做一些简单介绍


  Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(AppConst.BASE_URL)
                .client(okHttpClient)
                .addConverterFactory(MyGsonConverterFactory.create())
                .build();

     Api   api = retrofit.create(Api.class);
     
     api.onLogin("18201883983", "1111111", "1111111")
                .enqueue(new Callback<News>() {
                    @Override
                    public void onResponse(Call<News> call, Response<News> response) {
                        
                    }

                    @Override
                    public void onFailure(Call<News> call, Throwable t) {

                    }
                });
    @POST("user/login")
    @FormUrlEncoded
    @Headers({"CustomHeader1: customHeaderValue1", "CustomHeader2: customHeaderValue2"})
    Call<News> onLogin(@Field("username") String username, @Field("password") String password, @Field("repassword") String repassword);

`

Retrofit的创建

Builder是Retrofit 里面的静态内部类,使用的建造者模式,用于多参数设置,Retrofit创建的时候主要是设置OkHttpClient,CallAdapte,Converter, OkHttpClient是OkHttp请求设置;CallAdapte是为了适配RxJava,java8等,Converter是为了做数据解析,在最后调用build()的时候将收集的参数,传递到Retrofit的构造方法中,并返回一个Retrofit对象。

 Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(AppConst.BASE_URL)
                .client(client)
                .addConverterFactory(MyGsonConverterFactory.create())    
                 //   .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
public static final class Builder {
...
 public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {//1 判断之前传递的OkHttpClient是都为空
        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.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

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

      // 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);
      converterFactories.addAll(platform.defaultConverterFactories());

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

在上面代码中,关键的是就是callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));以及converterFactories.addAll(platform.defaultConverterFactories());,前者是设置默认的callAdapter,后者设置默认的数据解析器。但是我们在前面设置过.addConverterFactory(MyGsonConverterFactory.create())数据解析Converter,这里只会设置默认的CallAdapter,这里会将这个两个都保存在Retrofit中的两个集合中,后面根据传递过来的参数遍历获取。

那么跟着Platform类往里看defaultCallAdapterFactories()方法,如果callbackExecutor不为空,就返回一个ExecutorCallAdapterFactory对象,这个对象的作用就发起请求前的处理,在ExecutorCallAdapterFactory中主要是做线程切换,切换到主线程可以直接在数据返回的时候更新UI.ExecutorCallAdapterFactory对象蛮重要的,所以要搞清楚ExecutorCallAdapterFactory有什么用,什么时候用到.

class Platform {
...
 List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
      @Nullable Executor callbackExecutor) {
    if (callbackExecutor != null) {
      return singletonList(new ExecutorCallAdapterFactory(callbackExecutor));
    }
    return singletonList(DefaultCallAdapterFactory.INSTANCE);
  }
  ...
  }

ExecutorCallAdapterFactory类解析

final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
  final Executor callbackExecutor;

  ExecutorCallAdapterFactory(Executor callbackExecutor) {
    this.callbackExecutor = callbackExecutor;
  }

  @Override public @Nullable 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);
      }
    };
  }

  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;
    }

    @Override public void enqueue(final Callback<T> callback) {
      checkNotNull(callback, "callback == null");

      delegate.enqueue(new Callback<T>() {
        @Override public void onResponse(Call<T> call, final Response<T> response) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              if (delegate.isCanceled()) {
                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
              } else {
                callback.onResponse(ExecutorCallbackCall.this, response);
              }
            }
          });
        }

        @Override public void onFailure(Call<T> call, final Throwable t) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              callback.onFailure(ExecutorCallbackCall.this, t);
            }
          });
        }
      });
    }

    @Override public boolean isExecuted() {
      return delegate.isExecuted();
    }

    @Override public Response<T> execute() throws IOException {
      return delegate.execute();
    }

    @Override public void cancel() {
      delegate.cancel();
    }

    @Override public boolean isCanceled() {
      return delegate.isCanceled();
    }

    @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
    @Override public Call<T> clone() {
      return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
    }

    @Override public Request request() {
      return delegate.request();
    }
  }
}
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);
    }
  }
}

首先ExecutorCallAdapterFactory类继承于CallAdapter的内部类Factory,内部抽象类Factory只有一个抽象方法get()方法并返回一个CallAdapter<?, ?>.也就是说ExecutorCallAdapterFactory会实现get()方法,并返回一个CallAdapter,
但是外部接口CallAdapter中拥有需要实现的Type responseType()T adapt(Call<R> call)方法,分别返回一个Type以及一个泛型T.

那么我们在看看ExecutorCallAdapterFactory,到底Type和泛型T是干什么的。
ExecutorCallAdapterFactory首先实现了get方法(),根据returnType,调用了 Utils.getCallResponseType方法,返回一个Type。根据方法名字可以知道,Type是最后返回成数据要解析的对象类型,那么在前面肯定有一个地方设置了数据最后要解析成什么,然后拿到这个类型再传递到这里来了。

返回CallAdapter的时候,其再这里直接New了一个CallAdapter<Object, Call<?>>()对象,那么其实现的Type responseType()方法则将前面的Type给返回,这里注意看New的 CallAdapter中传递的两个参数;
一个是传递的Object,对应的是泛型R,最后在CallAdapter中的adapt(Call<Object> call)中Call的泛型对应的就是Object,第二个参数传送的是Call(Call的相关代码下面一结有铺上)。 也就是说T adapt(Call<R> call)方法方法要返回一个Call对象。接下来看CallAdapter中的adapt(Call<Object> call)方法

CallAdapter中的adapt(Call call)中携带了一个call过来了。而这个方法要返回一个Call,但是又传递了一个call过来,那直接返回不就好了吗?其实这是在前期发起请求的时候要做一些处理,这是就去前面我们说的线程切换。再看实现了Call<T>接口的ExecutorCallbackCall类,ExecutorCallbackCall首先实现了Call<T>接口中的所有方法, 在delegate.enqueue方法中其实做了些拦截。如果delegate.isCanceled(),取消了,就调用callback.onFailure(),不然就走callback.onResponse()
总结:ExecutorCallAdapterFactory主要是get方法中new的CallAdapter决定了之后是谁执行请求,并在ExecutorCallbackCall中做了部分状态拦截,在这里得到的call就是最后发起请求的,了解在赋值call很重要。
代码跟踪发现ExecutorCallAdapterFactory类在最后HttpServiceMethod类中获取CallAdapter的时候会调用Retrofit中的方法循环遍历得到,HttpServiceMethod类是非常重要的,在Retrofit调用create方法的时候会创建,到时候一起讲解,

发起请求的Call

Call的代码很简单,同步请求异步请求,是被被执行,取消,是否已经取消等方法,基本上实现这个方法就是发起请求开始拉数据了。

public interface Call<T> extends Cloneable {
  /**
   * Synchronously send the request and return its response.
   *
   * @throws IOException if a problem occurred talking to the server.
   * @throws RuntimeException (and subclasses) if an unexpected error occurs creating the request
   * or decoding the response.
   */
  Response<T> execute() throws IOException;

  /**
   * Asynchronously send the request and notify {@code callback} of its response or if an error
   * occurred talking to the server, creating the request, or processing the response.
   */
  void enqueue(Callback<T> callback);

  /**
   * Returns true if this call has been either {@linkplain #execute() executed} or {@linkplain
   * #enqueue(Callback) enqueued}. It is an error to execute or enqueue a call more than once.
   */
  boolean isExecuted();

  /**
   * Cancel this call. An attempt will be made to cancel in-flight calls, and if the call has not
   * yet been executed it never will be.
   */
  void cancel();

  /** True if {@link #cancel()} was called. */
  boolean isCanceled();

  /**
   * Create a new, identical call to this one which can be enqueued or executed even if this call
   * has already been.
   */
  Call<T> clone();

  /** The original HTTP request. */
  Request request();
}

retrofit.create(xxx.class)

到这里开始要创建一个retrofit了 具体的使用就是Api api = retrofit.create(Api.class),同时返回一个接口对象。下面我们看看create方法,


public final class 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();
          private final Object[] emptyArgs = new Object[0];

          @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);
            }
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }
  ...
  }

了解代理模式的定知道其create方法使用了动态代理。在设计retrofit的时候,设计者希望接口中包含发起网络的方法,方法上使用注解包含所有的参数和属性声明,而这个接口也并不需要实现对象,直接在运行时创建一个实现给这接口,这就是动态代理。
对于动态代理的原理和使用,这里不做多讲述。对于create方法中比较关键的return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);这一段代码我们需要知道。首先我们要知道public Object invoke(Object proxy, Method method, @Nullable Object[] args)这个方法中的参数意思
proxy:代表动态代理对象
method:代表正在执行的方法
args:代表当前执行方法传入的实参
返回值:表示当前执行方法的返回值
当我们调用create方法返回Api后,调用一个网络请求方法时,那么代理首先根据
loadServiceMethod(method).首先根据执行的方法返回一个ServiceMethod,然后将方法给的invoke去执行,再返回该方法的返回值。而ServiceMethod只是一个抽象类,真正的实现是在HttpServiceMethod类中。那么上面提到的,发起请求的其他必要条件必定在HttpServiceMethod中都有创建。

public final class 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;
  }
  ...
  }

HttpServiceMethod类以及request创建

这里首先看 ServiceMethod类中的RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method)方法。此方法是主要是创建了RequestFactory,为后面发起请求的Request做准备,所以很重要。

abstract class ServiceMethod<T> {
  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) {
      throw methodError(method,
          "Method return type must not include a type variable or wildcard: %s", returnType);
    }
    if (returnType == void.class) {
      throw methodError(method, "Service methods cannot return void.");
    }

    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

  abstract T invoke(Object[] args);
}
  1. 第一步 调用RequestFactory类的parseAnnotations()方法, 然后new Builder(retrofit, method),使用构建者模式将传递过来的retrofitmethod,保存到RequestFactory对象中,然后其build()方法 就是获取注解上所定义的属性
final class RequestFactory {
...
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
   return new Builder(retrofit, method).build();
 }
 ...
 }
  1. 根据method方法,获取注解上所声明的属性
    method.getAnnotations()获取方法上的所有注解, method.getGenericParameterTypes()
    方法返回一个Type对象的数组,它以声明顺序表示此Method对象表示的方法的形式参数类型。如果底层方法没有参数,则返回长度为0的数组
    method.getParameterAnnotations()获得一个注解的二维数组。第一个维度对应参数列表里参数的数目,第二个维度对应参数列表里对应的注解
final class RequestFactory {
...
static final class Builder {
...
Builder(Retrofit retrofit, Method method) {
    this.retrofit = retrofit;
    this.method = method;
    this.methodAnnotations = method.getAnnotations();
    this.parameterTypes = method.getGenericParameterTypes();
    this.parameterAnnotationsArray = method.getParameterAnnotations();
  }
  ...
  }
  ...
  }

3..build()方法build方法里面有两个for循环,最后分别调用的是parseMethodAnnotation()解析方法注解parseParameter()解析参数,两个方法很长,但是逻辑很简单,这里就一一贴出代码了,以下就是RequestFactory类最后获取的参数。

final class RequestFactory {
 private final Method method;
 private final HttpUrl baseUrl;
 final String httpMethod;
 private final @Nullable String relativeUrl;
 private final @Nullable Headers headers;
 private final @Nullable MediaType contentType;
 private final boolean hasBody;
 private final boolean isFormEncoded;
 private final boolean isMultipart;
 private final ParameterHandler<?>[] parameterHandlers;
 ...
 
 static final class Builder {
...
    RequestFactory build() {
     for (Annotation annotation : methodAnnotations) {
       parseMethodAnnotation(annotation);
     }

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

     if (!hasBody) {
       if (isMultipart) {
         throw methodError(method,
             "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
       }
       if (isFormEncoded) {
         throw methodError(method, "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++) {
       parameterHandlers[p] = parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p]);
     }

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

     return new RequestFactory(this);
   }
...
}
...
}

当执行到这里的时候,发起一个请求的Request已经算是创建了一部分了,要创建一个完整的Request,还需要 RequestBuilder类的帮助,
首先我们看看RequestBuilder会获取那些参数。


final class RequestBuilder {
...
  private final String method;
  private final HttpUrl baseUrl;
  private @Nullable String relativeUrl;
  private @Nullable HttpUrl.Builder urlBuilder;

  private final Request.Builder requestBuilder;
  private @Nullable MediaType contentType;

  private final boolean hasBody;
  private @Nullable MultipartBody.Builder multipartBuilder;
  private @Nullable FormBody.Builder formBuilder;
  private @Nullable RequestBody body;
...
}

RequestBuilder的创建在RequestFactory类的create方法中。主要是这句代码 RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers, contentType, hasBody, isFormEncoded, isMultipart);,create方法刚好就是返回发起请求所需要的okhttp3.Request ,也就是只要有一个类拥有RequestFactory的引用,那么调用其create()方法,就能返回一个Request。而根据下面return 方法就知道创建Request的所有参数已经获取完成。


final class RequestFactory {
...
okhttp3.Request create(Object[] args) throws IOException {
    @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
    ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;

    int argumentCount = args.length;
    if (argumentCount != handlers.length) {
      throw new IllegalArgumentException("Argument count (" + argumentCount
          + ") doesn't match expected count (" + handlers.length + ")");
    }

    RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl,
        headers, contentType, hasBody, isFormEncoded, isMultipart);

    List<Object> argumentList = new ArrayList<>(argumentCount);
    for (int p = 0; p < argumentCount; p++) {
      argumentList.add(args[p]);
      handlers[p].apply(requestBuilder, args[p]);
    }

    return requestBuilder.get()
        .tag(Invocation.class, new Invocation(method, argumentList))
        .build();
  }
...
}

callAdapter以及responseConverter的创建

继续看抽象类ServiceMethod,在其中还要一个方法 HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);很关键,在parseAnnotations()方法中,调用createCallAdapter()和createResponseConverter方法创建了callAdapterresponseConverter。callAdapter中的 T adapt(Call<R> call)方法是发起请求的入口。responseConverter是最后数据解析用的,但Converter不仅适配了数据解析,数据的加密也可以在里面实现。
接下来看HttpServiceMethod类,HttpServiceMethod继承ServiceMethod,实现invoke()方法。只需要得到CallAdapter对象调用 T adapt(Call call),就能发起请求,你可以回想下Retrofit的create()方法,是不是发现了什么?
callAdapter我们在上面遇到过ExecutorCallAdapterFactory类,其继承了CallAdapter.Factory,最后保存在Retrofit类的一个集合中。在HttpServiceMethod的invoke方法中调用 callAdapterT adapt(Call<R> call)方法, 在传递Call的时候我们看到这里New了一个OkHttpCall,将得到的requestFactory, args, callFactory, responseConverter参数传递进去了,这里算是可以发起请求了。 那么我们再看看请求后是怎么数据解析的,

看看responseConverter的创建


final class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {

...
  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
    Type responseType = callAdapter.responseType();
    if (responseType == Response.class || responseType == okhttp3.Response.class) {
      throw methodError(method, "'"
          + Utils.getRawType(responseType).getName()
          + "' is not a valid response body type. Did you mean ResponseBody?");
    }
    if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
      throw methodError(method, "HEAD method must use Void as response type.");
    }

    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
  }


...
 @Override ReturnT invoke(Object[] args) {
    return callAdapter.adapt(
        new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
  }
...
}

responseConverter的创建主要是为了解析数据,Retrofit的请求最后都是okhttp3去实现的,在okhttp3中数据请求返回的是一个okhttp3.Response,所以为了将Response的数据转换成我们所需要的模型对象,那么responseConverter就是用来做这样的事,我们看OkHttpCall类中的public void enqueue(final Callback<T> callback)方法,在其中 T body = responseConverter.convert(catchingBody);就是使用传递进来的responseConverter调用convert方法进行数据解析,那么回到前面Retroft-简单封装中查看MyGsonConverterFactory类中responseBodyConverter()方法,进入到ResponseBodyConverter类中,那么此处的responseConverter.convert()就是调用到我们自己实现的数据解析上了。到这里其实我们已经看到了OkHttpCall发起请求并且进行数据解析了,回到最上面的图,整个AndroidCallAdapter的流程就算是走完了。

final class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
...
 private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(
      Retrofit retrofit, Method method, Type responseType) {
    Annotation[] annotations = method.getAnnotations();
    try {
      return retrofit.responseBodyConverter(responseType, annotations);
    } catch (RuntimeException e) { // Wide exception range because factories are user code.
      throw methodError(method, e, "Unable to create converter for %s", responseType);
    }
  }
  ...
}
final class OkHttpCall<T> implements Call<T> {
...

 @Override public void enqueue(final Callback<T> callback) {
...
 call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
        
        Response<T> response;
        try {
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          throwIfFatal(e);
          callFailure(e);
          return;
        }    
  ...
  }

  Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();
    ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
    try {
      T body = responseConverter.convert(catchingBody);
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
      // If the underlying source threw an exception, propagate that rather than indicating it was
      // a runtime exception.
      catchingBody.throwIfCaught();
      throw e;
    }
  }
  
...
}

梳理

这里我们重新回忆下retrofit的整个启动过程,关键点首先是retrofit.build()方法,然后然后在里面进行了设置默认ExecutorCallAdapterFactory、线程切换以及数据解析的converter然后在retrofit.create(xx.class)
中调用了ServiceMethod.parseAnnotations(this, method)方法,返回一个ServiceMethod<?>,以及调用ServiceMethod的invoke(Object[] args)方法;在返回ServiceMethod<?>的时候开始创建发起请求的request,在HttpServiceMethod类中创建callAdapterresponseConverter;然后在调用invoke(Object[] args)方法的时候创建OkHttpCall,将Call传递到ExecutorCallAdapterFactory中。最后使用ExecutorCallAdapterFactory中传入的call也就是OkHttpCall发起请求,请求结束使用传递到OkHttpCall中的responseConverter进行数据解析完成整个请求。

retrofit框架使用了很多设计模式进行解耦。好的框架有很多细节处理值得学习,了解retrofit的使用和相关源码是学习框架的第一步,更好的是我们消化其技术转换成基本的原理,就像用积木搭好的摩天大楼,我们将其分解成小的积木,掌握每个积木的用途,经过锻炼,我们以后也能搭建摩天大楼!

秒懂Retrofit2之源码详解
Retrofit2之CallAdapter和Converter
Retrofit解析系列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值