阅读 165

读懂Retrofit

本文基于com.squareup.retrofit2:retrofit:2.9.0版本

Retrofit简单用法:

Retrofit retrofit = new Retrofit.Builder().baseUrl("\"https://api.github.com/\"").build();
        ApiService apiService = retrofit.create(ApiService.class);
        Call<Response> call = apiService.queryData("");
        call.enqueue(new Callback<List<Response>>() {
            @Override
            public void onResponse(Call<List<Response>> call, Response<List<Response>> response) {

            }

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

            }
        });
复制代码

上述代码是一个Retrofit的简单用法,大致流程为:
ApiService为定义请求方法的接口文件,通过retrofit创建一个ApiService对象apiService,然后通过apiService调用我们创建的请求方法queryData并且返回一个Call对象,然后调用call对象的enqueue的方法,发送网络请求。
那么在整个流程中,最关键的地方就是enqueue函数,这个函数将我们内部的数据发送到了网络中,那就首先来看enqueue函数

1,enqueue函数

我们通过Ctrl+W或者Ctrl+鼠标左键,进入到源码中的enqueue函数,发现是下面这样的

public interface Call<T> extends Cloneable {
/**
   * 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);
 }
复制代码

这是一个接口名称为Call的接口文件,enqueue是接口中的一个待实现的方法,那接下来就寻找这个方法实在哪实现的

2,retrofit.create(ApiService.class);

enqueue函数是被call对象调用的,call对象是被apiService调用queryData方法创建的,那么先看看apiService对象是怎么创建的

Call<Response> call = apiService.queryData("");
复制代码

apiService对象是被retrofit.create(ApiService.class)创建的,create函数的参数还是一个class文件,这是怎么创建的一个对象呢,这就涉及到了Retrofit的核心--动态代理了

  ApiService apiService = retrofit.create(ApiService.class);
复制代码

我们点进去源码,发现是这样的

  • validateServiceInterface()函数大致有两个作用:
    1,是对传入的ApiService.class进行了各种校验判断,主要有文件是不是接口文件,接口以及父接口是不是有泛型参数。
    2,有一个validateEagerly开关,打开的话,可以让我们在编译的过程中去检查定义的每个请求方法是否正确合法,关键代码是loadServiceMethod()函数。
  • Proxy.newProxyInstance就是实现动态代理的关键,首先动态代理就是在程序运行过程中,动态的生成一个class文件的代理对象,就比如在这里就是动态的生成了ApiService对象。

Proxy.newProxyInstance函数需要传入三个参数:
ClassLoader loader:类加载器
Class<?>[] interfaces:代理类可以同时实现多个接口,传入代理实现的接口文件的集合,Retrofit只有一个interface,就是放置所有请求方法的interface
InvocationHandler h:一个监听,执行代理对象中的方法时,会有回调给到监听中的invok函数,返回值为代理对象

所以我们重点看invoke函数:
第一个if判断是指如果是method对应的是Object.class,就直接调用invoke函数执行,并返回对应的代理对象,而我们传入的是个interface,所以不会走到if判断里,接着往下看
接下来就是return以及后面的代码码了,做了一个platform.isDefaultMethod(method)的判断,这个platform对象是一个判断当前平台的函数创建的,在这里是一个Android()对象,即platform = Android()。然后我们传入的interface中的方法都是自定义的,所以会走到loadServiceMethod(method).invoke(args),==通过下面的分析可以知道,loadServiceMethod()的返回值ServiceMethod的子类HttpServiceMethod实现了invoke()方法,接下来看看invoke()方法中做了什么==
接下来看看loadServiceMethod函数

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);
              }
            });
  }
复制代码
private final Platform platform = Platform.get();
class Platform {
  private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }

  private static Platform findPlatform() {
    return "Dalvik".equals(System.getProperty("java.vm.name"))
        ? new Android() //
        : new Platform(true);
  }
}
复制代码
3,loadServiceMethod(..)

1.1 loadServiceMethod()
根据下面代码可以看出,loadServiceMethod函数的返回值为ServiceMethod<?>,参数为一个Method,这个Method就是我们在接口中自定义的请求函数。

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;
  }
复制代码

1.2 ServiceMethod.parseAnnotations(...)
第一次发起请求的时候,serviceMethodCache中是没有缓存的,会通过.parseAnnotations(this, method)方法创建一个ServiceMethod对象,然后put到一个map缓存中。
通过下面的代码可以看出,经过一系列异常判断以后,会执行到return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory) 这行代码,我们点进去看看代码

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 @Nullable T invoke(Object[] args);
}
复制代码

1.3 HttpServiceMethod.parseAnnotations(..)
这段代码很长,我删减了一些异常判断以及对kotlin Suspend Function支持的代码。
这段代码中有很多重要的东西:

  • 获取了方法的注解Annotation[] annotations
  • 获取了方法的返回值类型 adapterType = = method.getGenericReturnType();
  • 创建了一个CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method, adapterType, annotations);
  • 获取了responseType = callAdapter.responseType();
  • 创建了Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType);
  • 获取了一个okhttp3.Call.Factory callFactory = retrofit.callFactory;
  • new了一个CallAdapted对象 new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);

接下来再看最后的返回值return new CallAdapted<>(...)

abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
    static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
            Retrofit retrofit, Method method, RequestFactory requestFactory) {
        boolean continuationWantsResponse = false;
        boolean continuationBodyNullable = false;

        Annotation[] annotations = method.getAnnotations();
        Type adapterType = method.getGenericReturnType();

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

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

        okhttp3.Call.Factory callFactory = retrofit.callFactory;
        
        return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
    }
}
复制代码

1.3 return new CallAdapted<>(...)       可以看到CallAdapted继承了HttpServiceMethod,实现了adapt方法。

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);
    }
  }
复制代码
3,HttpServiceMethod ---> invoke(...)

      1.1 可以看出invoke方法中创建了一个OkHttpCall()的对象,然后执行了adapt()方法。但是adapt()方法是一个抽象类,所以又要找到它实现的地方了...
通过上面2.1.3可以看出,其实adapt()的实现就在class CallAdapted<ResponseT, ReturnT>中

abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
  @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);
 }
复制代码

      1.2 点进去会发现,又是一个interface的方法,又要找到他的实现了....
仔细看,adapt()是由CallAdapted()构造函数传进来的callAdapter调用的,从2.1.2和2.1.3可以看出,传进来的callAdapter是通过CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method, adapterType, annotations)创建的,那就再看createCallAdapter()吧

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);
    }
  }
  
  public interface CallAdapter<R, T> {
     T adapt(Call<R> call);
  }
复制代码

      1.3 createCallAdapter(...)
从代码可以看出,createCallAdapter的返回值callAdapter是从callAdapterFactories这样一个list集合中获取的,那么这个list中的值是什么时候add进去的呢

abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {  
  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);
    }
  }
}
复制代码
public final class Retrofit {
  public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }
  
    public CallAdapter<?, ?> nextCallAdapter(
      @Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {

    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;
      }
    }
  }
}
复制代码

      1.4 在Retrofit.java中,全局搜索一下,会发现是在Retrofit build的时候add的,通过callAdapterFactories.addAll()方法,将值插入到了callAdapterFactorie集合中,那么接下来就该看platform.defaultCallAdapterFactories(callbackExecutor)是什么了

 public Retrofit build() {

        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.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

        return new Retrofit(
                callFactory,
                baseUrl,
                unmodifiableList(converterFactories),
                unmodifiableList(callAdapterFactories),
                callbackExecutor,
                validateEagerly);
    }
复制代码

      1.5 platform.defaultCallAdapterFactories(callbackExecutor)
先看看传入的callbackExecutor是什么,代码如下

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }
复制代码

而platform我们知道是一个Android()对象,那就看看Android()中的对应实现,可以看到通过Executor和Handler进行了线程的切换,将execute的Runnable切换到了主线程实现,知道了callbackExecutor参数是什么,那就接着继续看defaultCallAdapterFactories

static final class Android extends Platform {

    @Override
    public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }
    
    static final class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override
      public void execute(Runnable r) {
        handler.post(r);
      }
    }
}    
复制代码

忽略对hasJava8Types的判断,这是对Java8的支持,直接看else里的内容,是将DefaultCallAdapterFactory对象转化为了一个list返回。

  List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
      @Nullable Executor callbackExecutor) {
    DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
    return hasJava8Types
        ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
        : singletonList(executorFactory);
  }

复制代码

经过上面的流程以后,会可以发现在callAdapterFactories中获取到的callAdapter对象就是DefaultCallAdapterFactory, 那么adapt()方法的实现应该就在DefaultCallAdapterFactory中了,具体是不是呢,咱们点击去看看源码

4,DefaultCallAdapterFactory

      1.1 果然是有adapt()方法的,在CallAdapter对象中,实现了adapt方法,在adapt方法中,new了一个ExecutorCallbackCall对象,并且传入了一个Call对象和一个executor,这个executor我们知道是起切换线程作用的,那么Call对象是什么呢?,而且在class ExecutorCallbackCall中我们看到了熟悉的enqueue方法,这是怎么回事儿呢?要想解惑,那就需要看看这个Call对象是什么

final class DefaultCallAdapterFactory extends CallAdapter.Factory {
  private final @Nullable Executor callbackExecutor;

  DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
    this.callbackExecutor = callbackExecutor;
  }

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

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

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

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

      1.2 通过上面的3.1.1和3.1.2可以得知,这个Call对象就是一个OkHttpCall()对象,那么传入ExecutorCallbackCall的参数call就是OkHttpCall
1.3 然后从1,2和3可以总结出这样的一个方法调用链:
invoke[Proxy.newProxyInstance] -->
loadServiceMethod(method).invoke(args)[Proxy.newProxyInstance] -->
invoke(Object[] args)[HttpServiceMethod] -->
adapt(call, args)[HttpServiceMethod] -->
return callAdapter.adapt(call) 而adapt的返回值是一个ExecutorCallbackCall
1.4 那么我们通过动态代理的方式执行
Call call = apiService.queryData("ddd"); call.enqueue(..)的时候,就是执行了ExecutorCallbackCall中的enqueue方法,从4.1.3可以得知,delegate = OkHttpCall(),则 delegate.enqueue方法就是执行了OkHttpCall()中的enqueue方法,并且返回了网络请求的响应response,然后通过传进来的executor进行线程的切换,最终将值返回给call.enqueue()中的onResponse和onFailure

  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) {
      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));
            }
          });
    }
}
复制代码

到了这里,我们就以及形成了一个逻辑上的调用闭环,从call.enqueue()发送请求到获取返回值onResponse和onFailure,接下来该看看OkHttpCall()中的enqueue干了些什么了
通过createRawCall创建了一个call对象,然后执行了call对象的enqueue方法,那么这个call对象又是什么呢

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

        okhttp3.Call call;

        call = rawCall = createRawCall();

        call.enqueue(
                new okhttp3.Callback() {
                    @Override
                    public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
                        Response<T> response;
                        response = parseResponse(rawResponse);
                        callback.onResponse(OkHttpCall.this, response);
                    }

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

                    private void callFailure(Throwable e) {
                        callback.onFailure(OkHttpCall.this, e);
                    }
                });
    }
复制代码

经过一系列的朔源查找(有兴趣的可以自己查下源码),可以找到callFactory是Retrofit build过程中创建的一个属于okHttp的OkHttpClient对象,那么上面的call对象,就是OkHttpClient对象执行newCall返回的一个Call对象了,到这里就和okHttp网络访问框架联系起来了。最后调用的是okHttp的网络访问方法

  private okhttp3.Call createRawCall() throws IOException {
    okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }
复制代码

最后,关于Retrofit的源码流程已经差不多了,可能读起来会比较绕,因为很多参数是在Retrofit创建的时候就初始化的,很多方法也是由子类或者实现接口的方式实现的。所以记笔记就很重要,这篇文章也就当作我读源码的笔记了,有错误的地方,麻烦各位看客多指教

文章分类
Android