Retrofit 源码阅读

792 阅读12分钟

1.简单使用

// 接口代理类
interface WanAndroidApi {
    @GET("xxx/xx/xxx")
    fun getHomeList(
        @Path("page") page: Int
    ): Call<BaseBean<HomeDataBean?>?>?
}
// 建造retrofit对象,设置Gson转换工厂
retrofit = new Retrofit.Builder()
        .baseUrl(baseUrl)
        .addConverterFactory(GsonConverterFactory.create())
        .build();
// 创建接口对象        
service = retrofit.create(WanAndroidApi::class.java)
// 异步请求
service.getHomeList().enqueue(object : Callback<T> {
    override fun onResponse(call: Call<T>, response: Response<T>) {
        handler.obtainMessage(successId, response.body()).sendToTarget()
    }

    override fun onFailure(call: Call<T>, t: Throwable) {
        val throwable = HandlerException.handleException(t)
        handler.obtainMessage(errorid, throwable.message).sendToTarget()
    }
})

上面就是简单的使用了,建造retrofit对象,设置Gson转换仓库,创建接口实例,请求网络。

2. Retrofit.create方法

public <T> T create(final Class<T> service) {
  // 第一步 验证接口服务
  validateServiceInterface(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 @Nullable 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);
              }
              args = args != null ? args : emptyArgs;
              return platform.isDefaultMethod(method)
                  ? platform.invokeDefaultMethod(method, service, proxy, args)
                  : loadServiceMethod(method).invoke(args);
            }
          });
}

可以把这个方法的行为分为这两步,1、验证接口 2、返回动态代理类。什么是动态代理,动态代理就是在代码运行的时候去生成的类,而不是编译的时候。这被称为动态

2.1 Retrofit.validateServiceInterface方法

private void validateServiceInterface(Class<?> service) {
  // 第一块 如果传过来的class类不是interface则抛异常
  if (!service.isInterface()) { 
    throw new IllegalArgumentException("API declarations must be interfaces.");
  }
  
  // 第二块 父类或自身类存在范型则抛出异常 如(interface lala<T>{....})
  Deque<Class<?>> check = new ArrayDeque<>(1);
  check.add(service);
  while (!check.isEmpty()) {
    Class<?> candidate = check.removeFirst();
    if (candidate.getTypeParameters().length != 0) {
      StringBuilder message =
          new StringBuilder("Type parameters are unsupported on ").append(candidate.getName());
      if (candidate != service) {
        message.append(" which is an interface of ").append(service.getName());
      }
      throw new IllegalArgumentException(message.toString());
    }
    // 将传进来的类的父类放入队列中,如果不太懂可以看看getInterfaces方法
    Collections.addAll(check, candidate.getInterfaces());
  }

  // 调试使用 将类中的所有方法加载出来
  if (validateEagerly) {
    Platform platform = Platform.get();
    for (Method method : service.getDeclaredMethods()) {
      if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
        loadServiceMethod(method);
      }
    }
  }
}

这里有做两个抛出异常的判断,1、类是否为interface 2、是否类上有范型(如(interface lala<T>{....}))3、加载所有方法,这个为调试使用,默认为false,如有需要可以在构造Retrofit时设置validateEagerly方法。

小结:到这create方法就走完了,无非是判断传过来的类是否合规,然后返回动态代理类

3 回到动态代理中的代码 -- 如何加载方法的呢

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 @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
            // 如果方法属于object中的方法。直接调用。例如toString等等都方法
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            args = args != null ? args : emptyArgs;
            // 这里验证一些默认方法之类的,这种特性在java8以上才有
            return platform.isDefaultMethod(method)
                ? platform.invokeDefaultMethod(method, service, proxy, args)
                : loadServiceMethod(method).invoke(args);
          }
        });

当我们调用service.getHomeList()时就会,到达invocationHandler中的invoke方法。这里面的一些判断都写了注释不赘述了,继续往loadServiceMethod方法看

3.1 Retrofit.loadServiceMethod方法 ---(如何加载方法的呢)

ServiceMethod<?> loadServiceMethod(Method method) {
  // 尝试缓存中获取
  ServiceMethod<?> result = serviceMethodCache.get(method);
  if (result != null) return result; // 得到了直接返回

  // 没拿到 解析获取 然后 存入缓存中
  synchronized (serviceMethodCache) {
    result = serviceMethodCache.get(method);
    if (result == null) {
      // 解析注解来返回对应的method对象
      result = ServiceMethod.parseAnnotations(this, method);
      serviceMethodCache.put(method, result);
    }
  }
  return result;
}

这里的代码看下来,先从一个map中拿,拿到了就直接返回。没拿到就解析获取,获取后存入缓存中。那关键的代码就是解析获取那一行了。提一下:注意这里返回的是ServiceMethod对象,它内部有invoke方法

3.1.1 Retrofit.parseAnnotations方法

static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
  // 1
  RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
  // 2 这一块 是做方法返回类型合规判断
  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.");
  }
    // 3
  return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}

这里有两点比较奇怪,就是1和3,都是parseAnnotations方法,只不过是不同的类中的方法。具体是做什么的,先看第一个

3.1.1.1 RequestFactory.parseAnnotations方法

static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
  return new Builder(retrofit, method).build();
}

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

RequestFactory build() {
  for (Annotation annotation : methodAnnotations) {
    parseMethodAnnotation(annotation);
  }
  // 这下边做了很多合规性的判断,比方说:是否存在请求方式的注解
  ...
 
  return new RequestFactory(this);
}

private void parseMethodAnnotation(Annotation annotation) {
  // 这底下就是根据范型的类型。来对应的去采取相应解析策略
  if (annotation instanceof DELETE) {
    parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
  } else if (annotation instanceof GET) {
    parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
  } else if (annotation instanceof HEAD) {
    parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
  } else if (annotation instanceof PATCH) {
    parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
  } else if (annotation instanceof POST) {
    parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
  } else if (annotation instanceof PUT) {
    parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
  } else if (annotation instanceof OPTIONS) {
    parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
  } else if (annotation instanceof HTTP) {
    HTTP http = (HTTP) annotation;
    parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
  } else if (annotation instanceof retrofit2.http.Headers) {
    String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
    if (headersToParse.length == 0) {
      throw methodError(method, "@Headers annotation is empty.");
    }
    headers = parseHeaders(headersToParse);
  } else if (annotation instanceof Multipart) {
    if (isFormEncoded) {
      throw methodError(method, "Only one encoding annotation is allowed.");
    }
    isMultipart = true;
  } else if (annotation instanceof FormUrlEncoded) {
    if (isMultipart) {
      throw methodError(method, "Only one encoding annotation is allowed.");
    }
    isFormEncoded = true;
  }
}

这样就知道都做了啥了,首先这又是建造者模式,在构造方法中就直接去获取方法中的所有注解然后遍历的去解析对应的注解,解析完注解之后,在对方法进行合规性判断,当然这个代码很多,有兴趣可以自行查阅。这里也可以看出来retrofit支持很多的请求方式delete、patch和put等等都支持

小结:解析是根据获取方法中的所有注解,然后遍历方法的所有注解,然后对每个注解有相应的解析策略。其中还做了很多合规性判断,请求参数和注解请求方式等等。

4 回到3.1.1 的第三点

4.1 返回call对象

都知道retrofit是对okhttp的封装,那如何调用到okhttp的call呢?

static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
    Retrofit retrofit, Method method, RequestFactory requestFactory) {
  boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
  boolean continuationWantsResponse = false;
  boolean continuationBodyNullable = false;

  Annotation[] annotations = method.getAnnotations();
  Type adapterType;
  // 做了一些kt挂起方法的判断。这里省略了
  if (isKotlinSuspendFunction) {
    ......
  } else {
    adapterType = method.getGenericReturnType();
  }

  // 创建call适配器
  CallAdapter<ResponseT, ReturnT> callAdapter =
      createCallAdapter(retrofit, method, adapterType, annotations);
  // 下面是做了一些响应类型的合规性判断
  Type responseType = callAdapter.responseType();
  if (responseType == okhttp3.Response.class) {
    throw methodError(
        method,
        "'"
            + getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
  }
  if (responseType == Response.class) {
    throw methodError(method, "Response must include generic type (e.g., Response<String>)");
  }
  // TODO support Unit for Kotlin?
  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;
  if (!isKotlinSuspendFunction) {
    // 返回了Call适配器
    return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
  } else if (continuationWantsResponse) {
    ......
  } else {
    ......
  }
}

从retrofit稍微高一点的版本之后,开始支持kotlin的挂起方法,我这边就把相关的代码省略了,有兴趣可以自己扒一下。注意这里有创建一个响应后的响应转换器responseConverter,后面传给了Call对象,默认情况isKotlinSuspendFunction是false。这方法中所做的事情是返回callAdapted。这里不禁发出疑问,啥东西啊,之前要返回一个ServiceMethod,这里返回一个callAdapted。都在干嘛啊,要绕晕了!不急,先梳理一下这里的类结构

abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
  static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT>
    
}

这样就清晰了是不,callAdapted是ServiceMethod后辈类。那这里就没啥返回类型上的疑问了,

但不懂为什么要走这么多层。我们把思绪拉回到动态代理生成的代码中的这段代码

return platform.isDefaultMethod(method)
    ? platform.invokeDefaultMethod(method, service, proxy, args)
    : loadServiceMethod(method).invoke(args);

我们加载方法是为了调用它的invoke方法啊,那上头是返回的是callAdapted类型,瞧瞧他的invoke方法

static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
  private final CallAdapter<ResponseT, ReturnT> callAdapter;

  CallAdapted(
      RequestFactory requestFactory,
      okhttp3.Call.Factory callFactory,
      Converter<ResponseBody, ResponseT> responseConverter,
      CallAdapter<ResponseT, ReturnT> callAdapter) {
    super(requestFactory, callFactory, responseConverter);
    this.callAdapter = callAdapter;
  }

  @Override
  protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
    return callAdapter.adapt(call);
  }
}

他就潦草几句代码,并没有invoke方法啊!我哭死,由于继承关系,那我们就去他的父类HttpServiceMethod中找吧!

@Override
final @Nullable ReturnT invoke(Object[] args) {
  Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
  return adapt(call, args);
}

protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);

功夫不负有心人,果然在他的父类中找到了相关方法,这里实例化了一个一个OkHttpCall然后调用了他的自身adapt方法。这个时候我们回看回看HttpServiceMethod.parseAnnotations方法就明白了这里用子类的意义了,如果方法是kotlin的挂起方法,那么会返回其他的类,当然这个类也是继承HttpServiceMethod,他也实现了adapt方法。这就解释得通了,由于有不同策略所以使用的相应的自类来进行处理。这里要留意,他传到adapt里的是OkHttpCall对象,后续会用到

看CallAdapted的adapt方法。

@Override
protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
  return callAdapter.adapt(call);
}

很简单,就一行代码,调用了callAdapter的adapt。继续往下看。

public interface CallAdapter<R, T> {
    T adapt(Call<R> call);
}

亲娘诶,咋是一个interfeca勒。有得返回查看callAdapter是如何创建出来的了。

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

在HttpServiceMethod.parseAnnotations方法中是这样创建的,继续挖createCallAdapter方法。下面就把接下去的代码调出的所有方法粘贴出来了

// HttpServiceMethod类的方法中
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) { // Wide exception range because factories are user code.
    throw methodError(method, e, "Unable to create call adapter for %s", returnType);
  }
}

// Retrofit类的方法中
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
  return nextCallAdapter(null, returnType, annotations);
}

public CallAdapter<?, ?> nextCallAdapter(
    @Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
  Objects.requireNonNull(returnType, "returnType == null");
  Objects.requireNonNull(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;
    }
  }
  // 没取到就抛异常
  StringBuilder builder =
      new StringBuilder("Could not locate call adapter for ").append(returnType).append(".\n");
  if (skipPast != null) {
    builder.append("  Skipped:");
    for (int i = 0; i < start; i++) {
      builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
    }
    builder.append('\n');
  }
  builder.append("  Tried:");
  for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
    builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
  }
  throw new IllegalArgumentException(builder.toString());
}

最终调用到了Retrofit类中的nextCallAdapter方法,但其实这个方法不用细看了,都是从一个集合中取,没取到就抛异常。所以应该关注这个集合是从哪里设置的。我们点击这个callAdapterFactories参数会发现他在Retrofit的构造方法中才会被赋值,但建造者的使用,所以就在建造者的build方法中能够找到相关代码是

// Retrofit.Builder的build方法中
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));


// platform中的代码
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
    @Nullable Executor callbackExecutor) {
  DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
  return hasJava8Types
      ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
      : singletonList(executorFactory);
}
// DefaultCallAdapterFactorie 中的get方法
@Override
public @Nullable CallAdapter<?, ?> get(
    Type returnType, Annotation[] annotations, Retrofit retrofit) {
  if (getRawType(returnType) != Call.class) {
    return null;
  }
  if (!(returnType instanceof ParameterizedType)) {
    throw new IllegalArgumentException(
        "Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
  }
  final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);

  final Executor executor =
      Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
          ? null
          : callbackExecutor;

  return new CallAdapter<Object, Call<?>>() {
    @Override
    public Type responseType() {
      return responseType;
    }

    @Override
    public Call<Object> adapt(Call<Object> call) {
      return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
    }
  };
}

其中他的adapt方法会返回call对象,默认情况下executor不会为空,除非在注解中存在SkipCallbackExecutor的实例。如果executor为空就会返回上面的OkHttpCall对象,否则返回 ExecutorCallbackCall对象。但是call传入到了ExecutorCallbackCall中。

小结:到这里从使用动态代理类里的方法到此就结束了(例如使用代码中的service.getHomeList())。最后是返回了Call对象,默认返回的是ExecutorCallbackCall对象,但目前还没有调用到OKHttp的Call

4.2 call对象的enqueue方法

在获取到Call对象后,肯定是要进行网络请求的。基于4.1的小结,call对象默认情况是ExecutorCallbackCall对象。我们直接看他的enqueue方法即可。

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

@Override
public void enqueue(final Callback<T> callback) {
  Objects.requireNonNull(callback, "callback == null");
  // 1.调用了OkHttpCall的enqueue方法
  delegate.enqueue(
      new Callback<T>() {
        @Override
        public void onResponse(Call<T> call, final Response<T> response) {
          // 2.这里使用了一个executor,线程切换了
          callbackExecutor.execute(
              () -> {
                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) {
          // 2.这里使用了一个executor,线程切换了
          callbackExecutor.execute(() -> callback.onFailure(ExecutorCallbackCall.this, t));
        }
      });
}

这里不难看出delegate是OkHttpCall对象,因为在初始化ExecutorCallbackCall对象时传入了OkHttpCall。1、enqueue方法中调用了OKHttpCall的enqueue方法。2、在回调中切换了线程

4.2.1 OkHttpCall.enqueue ---如何调用到的OkHttp的Call

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

  okhttp3.Call call;
  Throwable failure;

  synchronized (this) {
    if (executed) throw new IllegalStateException("Already executed.");
    executed = true;

    call = rawCall;
    failure = creationFailure;
    if (call == null && failure == null) {
      try {
        // 创建OkHttp的Call
        call = rawCall = createRawCall();
      } catch (Throwable t) {
        throwIfFatal(t);
        failure = creationFailure = t;
      }
    }
  }

  if (failure != null) {
    callback.onFailure(this, failure);
    return;
  }

  if (canceled) {
    call.cancel();
  }

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

          try {
            callback.onResponse(OkHttpCall.this, response);
          } catch (Throwable t) {
            throwIfFatal(t);
            t.printStackTrace(); // TODO this is not great
          }
        }

        @Override
        public void onFailure(okhttp3.Call call, IOException e) {
          callFailure(e);
        }

        private void callFailure(Throwable e) {
          try {
            callback.onFailure(OkHttpCall.this, e);
          } catch (Throwable t) {
            throwIfFatal(t);
            t.printStackTrace(); // TODO this is not great
          }
        }
      });
}

private okhttp3.Call createRawCall() throws IOException {
  // 这里callFactory.newCall方法就跑到了okHttpClient的newCall方法
  okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
  if (call == null) {
    throw new NullPointerException("Call.Factory returned null.");
  }
  return call;
}

这里就终于走到了OkHttp中的代码了,okhttp就不说了,上篇文章有说过 juejin.cn/post/723451…

但我们还是看看OkHttpClient的newCall方法吧

@Override public Call newCall(Request request) {
  return RealCall.newRealCall(this, request, false /* for web socket */);
}

这里返回了OkHttp的RealCall对象,这样Retrofit就和okhttp串起来了

4.2.2 切换线程 ---为什么说Retrofitd可以在回调中直接渲染ui

那为什么在retrofit的回调里可以切换线程呢?来看代码

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

        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          throwIfFatal(t);
          t.printStackTrace(); // TODO this is not great
        }
      }

      @Override
      public void onFailure(okhttp3.Call call, IOException e) {
        callFailure(e);
      }

      private void callFailure(Throwable e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          throwIfFatal(t);
          t.printStackTrace(); // TODO this is not great
        }
      }
    });

在OkHttpCall类中调用OkHttp的Call的enqueue方法的回调中并没有切换线程,只是把相关数据处理放到Retrofit的回调中。之前说过Retrofit中的call是ExecutorCallbackCall对象,在他的回调中确实是有线程切换的啊!那这个线程是怎么切换到主线程的呢?

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

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

  delegate.enqueue(
      new Callback<T>() {
        @Override
        public void onResponse(Call<T> call, final Response<T> response) {
          callbackExecutor.execute(
              () -> {
                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(() -> callback.onFailure(ExecutorCallbackCall.this, t));
        }
      });
}

线程是从外面传过来的,所以又得回头去追踪代码。代码回倒这边就直接粘贴了

DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
  this.callbackExecutor = callbackExecutor;
}
......
@Override
public Call<Object> adapt(Call<Object> call) {
  return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
}
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
    @Nullable Executor callbackExecutor) {
  DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
      ......
}
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));

代码往回倒就发现了这个线程是由platform.defaultCallbackExecutor()提供,稍微介绍一下Platform这个类他是一个平台类,他的实例方法

private static Platform findPlatform() {
  return "Dalvik".equals(System.getProperty("java.vm.name"))
      ? new Android() //
      : new Platform(true);
}

android的虚拟机是Dalvik所以用的是Android

static final class Android extends Platform {
  Android() {
    super(Build.VERSION.SDK_INT >= 24);
  }

  @Override
  public Executor defaultCallbackExecutor() {
    return new MainThreadExecutor();
  }

  @Nullable
  @Override
  Object invokeDefaultMethod(
      Method method, Class<?> declaringClass, Object object, Object... args) throws Throwable {
    if (Build.VERSION.SDK_INT < 26) {
      throw new UnsupportedOperationException(
          "Calling default methods on API 24 and 25 is not supported");
    }
    return super.invokeDefaultMethod(method, declaringClass, object, args);
  }

  static final class MainThreadExecutor implements Executor {
    private final Handler handler = new Handler(Looper.getMainLooper());

    @Override
    public void execute(Runnable r) {
      handler.post(r);
    }
  }
}

啊!到这里就知道他retrofit回调能够直接刷新ui到原因啦,是因为回调是在主线程,当然得严谨一些,在OkHttpCall的回调中还是非主线程,到ExecutorCallbackCall到回调中时就切换到了主线程。切换线程的方式是通过handler。

5.自动转换json --如何支持自动转换的

retrofit = new Retrofit.Builder()
        .baseUrl(baseUrl)
        .client(httpClient)
        .addConverterFactory(GsonConverterFactory.create())
        .build();

添加一行代码addConverterFactory即可。

5.1 请求转换

public final class GsonConverterFactory extends Converter.Factory {

  public static GsonConverterFactory create() {
    return create(new Gson());
  }

  @SuppressWarnings("ConstantConditions") // Guarding public API nullability.
  public static GsonConverterFactory create(Gson gson) {
    if (gson == null) throw new NullPointerException("gson == null");
    return new GsonConverterFactory(gson);
  }

  private final Gson gson;

  private GsonConverterFactory(Gson gson) {
    this.gson = gson;
  }

  @Override
  public Converter<ResponseBody, ?> responseBodyConverter(
      Type type, Annotation[] annotations, Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonResponseBodyConverter<>(gson, adapter);
  }

  @Override
  public Converter<?, RequestBody> requestBodyConverter(
      Type type,
      Annotation[] parameterAnnotations,
      Annotation[] methodAnnotations,
      Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonRequestBodyConverter<>(gson, adapter);
  }
}

看到了这个类里主要行为就有有一个gson成员,两个方法,一个方法提供响应转换,一个提供请求转换。

这边就快进了,请求转换是在解析方法中的解析参数RequestFactory.parseParameter方法中

Converter<?, RequestBody> converter =
    retrofit.requestBodyConverter(type, annotations, methodAnnotations);
return new ParameterHandler.Header<>(name, converter).iterable();
final ParameterHandler<Iterable<T>> iterable() {
  return new ParameterHandler<Iterable<T>>() {
    @Override
    void apply(RequestBuilder builder, @Nullable Iterable<T> values) throws IOException {
      if (values == null) return; // Skip null values.

      for (T value : values) {
        ParameterHandler.this.apply(builder, value);
      }
    }
  };
}
static final class Header<T> extends ParameterHandler<T> {
  private final String name;
  private final Converter<T, String> valueConverter;

  Header(String name, Converter<T, String> valueConverter) {
    this.name = Objects.requireNonNull(name, "name == null");
    this.valueConverter = valueConverter;
  }

  @Override
  void apply(RequestBuilder builder, @Nullable T value) throws IOException {
    if (value == null) return; // Skip null values.
    // 这里convert方法就进行了转换
    String headerValue = valueConverter.convert(value);
    if (headerValue == null) return; // Skip converted but null values.

    builder.addHeader(name, headerValue);
  }
}

解析方法中的解析参数是给每个param都大致存了对应的请求转换器,上面举例的是header。到调用convert方法就去进行转换了,看看请求转换里的代码。

final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
  private static final MediaType MEDIA_TYPE = MediaType.get("application/json; charset=UTF-8");
  private static final Charset UTF_8 = Charset.forName("UTF-8");

  private final Gson gson;
  private final TypeAdapter<T> adapter;

  GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
    this.gson = gson;
    this.adapter = adapter;
  }

  @Override
  public RequestBody convert(T value) throws IOException {
    // 转换代码
    Buffer buffer = new Buffer();
    Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
    JsonWriter jsonWriter = gson.newJsonWriter(writer);
    adapter.write(jsonWriter, value);
    jsonWriter.close();
    return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
  }
}

其中type方式是‘application/json’,需要注意

5.2 响应转换

还记得上面要大家注意到传给call的响应转换器嘛,在HttpServiceMethod.parseAnnotations方法中。

Converter<ResponseBody, ResponseT> responseConverter =
    createResponseConverter(retrofit, method, responseType);
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);

他的后续createResponseConverter这里就不走了,跟callAdapted类似都是跑到了Retrofit里的构造器中。

转换器还被传到了Call对象中。在调用OkHttp的Call对象请求的回调中响应时触发转换。

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

        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          throwIfFatal(t);
          t.printStackTrace(); // TODO this is not great
        }
      }

      @Override
      public void onFailure(okhttp3.Call call, IOException e) {
        callFailure(e);
      }

      private void callFailure(Throwable e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          throwIfFatal(t);
          t.printStackTrace(); // TODO this is not great
        }
      }
    });
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
  ResponseBody rawBody = rawResponse.body();

  // Remove the body's source (the only stateful object) so we can pass the response along.
  rawResponse =
      rawResponse
          .newBuilder()
          .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
          .build();

  int code = rawResponse.code();
  if (code < 200 || code >= 300) {
    try {
      // Buffer the entire body to avoid future I/O.
      ResponseBody bufferedBody = Utils.buffer(rawBody);
      return Response.error(bufferedBody, rawResponse);
    } finally {
      rawBody.close();
    }
  }

  if (code == 204 || code == 205) {
    rawBody.close();
    return Response.success(null, rawResponse);
  }

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

排除了其他的状态码,到最后转换。最后贴上响应转换器代码

final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
  private final Gson gson;
  private final TypeAdapter<T> adapter;

  GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
    this.gson = gson;
    this.adapter = adapter;
  }

  @Override
  public T convert(ResponseBody value) throws IOException {
    JsonReader jsonReader = gson.newJsonReader(value.charStream());
    try {
      T result = adapter.read(jsonReader);
      if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
        throw new JsonIOException("JSON document was not fully consumed.");
      }
      return result;
    } finally {
      value.close();
    }
  }
}

确实精妙的代码。

小结:在解析方法中的解析参数时,会把对应的参数解析json,用于请求。并且在加载方法时,把响应转换器也设置给call了。当请求返回时执行回调会触发转换响应json。

当然个人还存在一个问题的,从头到尾,内部全部使用的是范型,是如何避免范型擦除机制的,特别是在响应回来进行转换的时候。我目前个人只能全部归结到动态代理上,希望大佬们可以指点指点。