Retrofit 2调用流程解析

2016-03-08  本文已影响0人  BlackL

Retrofit使用

若要请求api

https://api.github.com/users/{user}/repos

需要先创建一个接口

public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}

然后创建一个Retrofit对象

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com")
    .build();

GitHubService service = retrofit.create(GitHubService.class);

可以看到通过retrofit.create()方法,retrofit为我们创建了一个GitHubService的实现,感觉很不可思议。
紧接着就可以通过这个GitHubService的实现对象去请求网络了

Call<List<Repo>> repos = service.listRepos("octocat");

// Fetch and print a list of the contributors to the library.
List<Contributor> contributors = call.execute().body();

看到这里总是很疑惑,retrofit是如何用我们提供的接口来为我们创建出一个实例的呢?

Retrofit调用流程

从上面我们可以看到service实例是通过retrofit.create()方法获得的,那我们不看一下这个create()方法

@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
  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, 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 loadMethodHandler(method).invoke(args);
          }
        });
  }

可以看到该方法返回的并不是一个service接口的实例,而是一个动态代理对象,而他又是怎么通过动态代理去发送网络请求的呢?我们就需要查看

return loadMethodHandler(method).invoke(args);

这行代码的返回结果了,去查看loadMethodHandler()方法

private final Map<Method, MethodHandler> methodHandlerCache = new LinkedHashMap<>();

MethodHandler loadMethodHandler(Method method) {
    MethodHandler handler;
    synchronized (methodHandlerCache) {
      handler = methodHandlerCache.get(method);
      if (handler == null) {
        handler = MethodHandler.create(this, method);
        methodHandlerCache.put(method, handler);
      }
    }
    return handler;
}

可以看到该方法先去试图从methodHandler的缓存map中去寻找相应的methodHandler,若不存在再去创建对应方法的MethodHandler,获得了相应的MethodHandler实例后再去调用去invoke()方法来发送请求。
继续查看MethodHandler的invoke()方法

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

其中callAdapter.adapt()方法负责把service中的返回类型转换成其他类型,例如RxJavaCallAdapter把返回结果转换成了Observable类型
可以看到adapt方法中传入了一个OkHttpCall参数,而最后发送出网络请求的正是在该类的

@Override public void enqueue(final Callback<T> callback)
@Override public Response<T> execute() throws IOException

这两个方法中。相关的Http请求信息则封装在了requestFactory这个对象中。

这样整个流程就清楚了,可以看到这与我们一般使用动态代理的方法是不同的。这里对动态代理的使用是通过调用动态代理对象的相应方法,去生成一个Http请求再来发送这个请求。而service接口中方法的信息则是通过反射来得到的。

</br>

上一篇下一篇

猜你喜欢

热点阅读