Retrofit2源码分析

896 阅读5分钟

本文基于Retrofit2.5代码分析。 github.com/square/retr…

1. 分析思路:

从使用层面,一点点分析源码的具体实现。

2. 基本用法

2.1 Retrofit对象创建

// Create a very simple REST adapter which points the GitHub API.
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .addConverterFactory(GsonConverterFactory.create())
    .build();

使用的是Builder模式,利用Builder来创建需要的配置。

2.2 定义API接口

public interface GitHub {
  @GET("/repos/{owner}/{repo}/contributors")
  Call<List<Contributor>> contributors(
      @Path("owner") String owner,
      @Path("repo") String repo);
}

首先,要定义一个接口,方法是具体的网络接口请求。 主要通过注解来设置网络请求的参数(POST/GET、Path),后面在调用接口时会通过注解获取。 2.3 创建接口对象

// Create an instance of our GitHub API interface.
GitHub github = retrofit.create(GitHub.class);

调用create()方法,创建接口对象。

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

通过动态代理方式Proxy.newProxyInstance来创建具体的对象。所有对代理对象的方法的调用,都会回调到invoke方法。

使用动态代理的好处,可以定义多个API接口,而Retrofit只需要利用动态代理,统一代码,不需要关心业务具体使用哪个接口。

2.4 调用API方法,获取回调

// Create a call instance for looking up Retrofit contributors.
Call<List<Contributor>> call = github.contributors("square", "retrofit");

对接口方法的调用,都会执行代理的InvocationHandler的invoke()方法。

Retrofit封装了一个ServiceMethod对象,下面看下如何创建的ServiceMethod。

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;
}
abstract class ServiceMethod<T> {
  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    // 先解析注解,获取Request相关参数,比如前面定义的POST/GET Path等
    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.");
    }
 
    // 创建ServiceMethod对象
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }
 
  abstract @Nullable T invoke(Object[] args);
}

下面重点介绍如何创建的ServiceMethod对象

/** Adapts an invocation of an interface method into an HTTP call. */
final class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
  /**
   * Inspects the annotations on an interface method to construct a reusable service method that
   * speaks HTTP. This requires potentially-expensive reflection so it is best to build each service
   * method only once and reuse it.
   */
  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
    ......
    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);
 
    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
  }
  ......
}

主要有3个对象callFactory,callAdapter,responseConverter

callAdapter 把 retrofit2.Call 转为 T(注意和 okhttp3.Call 区分开来,retrofit2.Call 表示的是对一个 Retrofit 方法的调用),这个过程会发送一个 HTTP 请求,拿到服务器返回的数据(通过 okhttp3.Call 实现),并把数据转换为声明的 T 类型对象(通过 Converter<F, T> 实现);

responseConverter 是 Converter<ResponseBody, T> 类型,负责把服务器返回的数据(JSON、XML、二进制或者其他格式,由 ResponseBody 封装)转化为 T 类型的对象;

callFactory 负责创建 HTTP 请求,HTTP 请求被抽象为了 okhttp3.Call 类,它表示一个已经准备好,可以随时执行的 HTTP 请求;

分析下CallAdapter的创建过程

/**
 * Returns the {@link CallAdapter} for {@code returnType} from the available {@linkplain
 * #callAdapterFactories() factories}.
 *
 * @throws IllegalArgumentException if no call adapter available for {@code type}.
 */
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
  return nextCallAdapter(null, returnType, annotations);
}
 
/**
 * Returns the {@link CallAdapter} for {@code returnType} from the available {@linkplain
 * #callAdapterFactories() factories} except {@code skipPast}.
 *
 * @throws IllegalArgumentException if no call adapter available for {@code type}.
 */
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;
    }
  }
  ......
}

是从Retrofit中的callAdapterFactories列表中获取的。

/**
 * Create the {@link Retrofit} instance using the configured values.
 * <p>
 * Note: If neither {@link #client} nor {@link #callFactory} is called a default {@link
 * OkHttpClient} will be created and used.
 */
public Retrofit build() {
  ......
  // 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);
}

可见,是根据用户设置和Platform共同生成的列表。

static class Android extends Platform {
  @IgnoreJRERequirement // Guarded by API check.
  @Override boolean isDefaultMethod(Method method) {
    if (Build.VERSION.SDK_INT < 24) {
      return false;
    }
    return method.isDefault();
  }
 
  @Override public Executor defaultCallbackExecutor() {
    return new MainThreadExecutor();
  }
 
  @Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
      @Nullable Executor callbackExecutor) {
    if (callbackExecutor == null) throw new AssertionError();
    ExecutorCallAdapterFactory executorFactory = new ExecutorCallAdapterFactory(callbackExecutor);
    return Build.VERSION.SDK_INT >= 24
      ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
      : singletonList(executorFactory);
  }
}

由前面代码可知,Retrofit利用Factory模式,通过调用CallAdater.Factory.get()方法创建的CallAdapter对象。

Converter创建源码,同CallAdapter,也是利用Facotry模式,通过调用Converter.Factory.get()方法创建的Convert对象。

CallFactory是OkHttp中的Call.Factory的对象,默认在Retrofit.Builder中创建,如果使用者,不设置,则创建。默认使用OkHttpClient。

public Retrofit build() {
  if (baseUrl == null) {
    throw new IllegalStateException("Base URL required.");
  }
 
  okhttp3.Call.Factory callFactory = this.callFactory;
  if (callFactory == null) {
    callFactory = new OkHttpClient();
  }
  ......
}

以上,创建完成ServiceMethod。

下面开始分析ServiceMethod.invoke()方法

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

就是执行CallAdapter.adapt()方法。

我们知道CallAdapter是通过CallAdater.Factory.get()创建的。

Android中使用的是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);
      }
    };
  }
 
  // 只是做了一层封装,具体的执行,都是调用的构造方法中的Call<T>对象。即都是调用的OkHttpCall
  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()) {
                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 Response<T> execute() throws IOException {
      return delegate.execute();
    }
  ......
  }
}

以上即完成了接口方法的调用,会返回retrofit2.Call对象。

2.4 通过回调Call调用执行具体的网络请求

// Fetch and print a list of the contributors to the library.
List<Contributor> contributors = call.execute().body();
或
call.enqueue(new Callback<List<Contributor>>() {
  @Override
  public void onResponse(Call<List<Contributor>> call, Response<List<Contributor>> response) {
     
  }
  @Override
  public void onFailure(Call<List<Contributor>> call, Throwable t) {
     
  }
});

OkHttpCall其实是对okhttp3.Call的封装,最后都是调用okhttp3.Call的enqueue和execute方法。

到此,Retrofit的流程基本分析完成了。

最后提供一张整体框架图

参考:

blog.piasy.com/2016/06/25/… www.jianshu.com/p/fb8d21978…