并不想将Retrofit放在okhttp中,但是感觉单独出来太占地了,但是Retrofit中还是有使用到okhttp的,所以将其放在一起吧。
本文分析的Retrofit是基于2.5.0,也就是现在的最新版本。
具体的下载: 地址
先讲讲题外的,当你将上述工程拷贝下来时,发现这个工程并不是一个Android的工程(有点坑了),刚开始我的做法是将其中的目录有关Retrofit的项目工程复制出来粘贴到AndroidStduio中,但是发现这个过程中还是有其他问题(注解报错,构建Retrofi实例的时候出现解析gson的报错),我们还要单独在gralde文件中引入其他库。这样太麻烦了
implementation 'com.google.code.findbugs:jsr305:3.0.2'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0' // 用Gson解析json的转换器
当然还有其他方法,上面的工程其实是一个java工程,只需要下载IDEA工具(网上有破解版的),等待编译成功之后,运行“SimpleService”文件即可执行。
当然在AndroidStudio中添加引入不可能用上面的那种方法(太麻烦了),可以在工程中添加gradle依赖
implementation 'com.squareup.retrofit2:converter-gson:2.5.0' // 用Gson解析json的转换器
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
这种方法的缺点是分析代码流程中会有问题,我说的问题只是说分析流程有些许问题,如果这些你感觉可以忽略,那么完全没必要用IDEA来编译项目,可以使用AndroidStudio来分析。
至于Retrofit使用的话,Retrofit类注解中已经有例子,并且有官方文档
/**
* Retrofit adapts a Java interface to HTTP calls by using annotations on the declared methods to
* define how requests are made. Create instances using {@linkplain Builder
* the builder} and pass your interface to {@link #create} to generate an implementation.
* <p>
* For example,
* <pre><code>
* Retrofit retrofit = new Retrofit.Builder()
* .baseUrl("https://api.example.com/")
* .addConverterFactory(GsonConverterFactory.create())
* .build();
*
* MyApi api = retrofit.create(MyApi.class);
* Response<User> user = api.getUser().execute();
* </code></pre>
*
* @author Bob Lee (bob@squareup.com)
* @author Jake Wharton (jw@squareup.com)
*/
public final class Retrofit {
...
}
现在来分析下Retrofit的实现过程,需要先熟悉动态代理,如果忘记的话可以看看这篇动态代理。
下面以SimpleService 为例,来分析整个实现过程。
public final class SimpleService {
public static final String API_URL = "https://api.github.com:443/";
public static class Contributor {
public final String login;
public final int contributions;
public Contributor(String login, int contributions) {
this.login = login;
this.contributions = contributions;
}
}
public interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
Call<List<Contributor>> contributors(
@Path("owner") String owner,
@Path("repo") String repo);
}
public static void main(String... args) throws IOException {
// Create a very simple REST adapter which points the GitHub API.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_URL)
.addConverterFactory(GsonConverterFactory.create())
.build(); //1
// Create an instance of our GitHub API interface.
GitHub github = retrofit.create(GitHub.class); //2
// Create a call instance for looking up Retrofit contributors.
Call<List<Contributor>> call = github.contributors("square", "retrofit");//3
// Fetch and print a list of the contributors to the library.
List<Contributor> contributors = call.execute().body();//4
for (Contributor contributor : contributors) {
System.out.println(contributor.login + " (" + contributor.contributions + ")");
}
}
- 1 是Retrofit的构建过程
- 2是使用动态代理生成代理类的过程
- 3是调用代理类中的方法
- 4是通过okhttpclient请求数据的过程
Retrofit的构建过程使用了Builder设计模式,首先是添加请求的baseUrl地址,注意baseUrl的格式是这种“protocol://hostname:port/”例如:https://api.github.com/,端口号可加可不加。addConverterFactory()是一种一种数据序列化和反序列话对象的转换器。最后再看下build()方法。
public Retrofit build() {
//如果baseUrl为空出现异常
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
//okhttp的工厂类
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
// 生成一个默认的okhttpclient,用于发送http请求和接受
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.
// callAdapter集合
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);
}
}
其中Builde的默认构造方法也需要看下,根据不同编译环境,得到不同编译平台,在build()方法中有使用,现在使用的idea构建的的所以是Java8的版本(还有Android的版本)。
public Builder() {
this(Platform.get());
}
Builder(Platform platform) {
this.platform = platform;
}
---
class Platform {
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
// 判断当前的环境
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
....
}
再看下retrofit.create(GitHub.class)方法。
public <T> T create(final Class<T> service) {
//验证这个是不是接口
Utils.validateServiceInterface(service);
//默认false
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 @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类
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
// 接口中的方法都是public
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//生成方法的ServiceMethod实例
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
// return null;
}
});
}
- 首先是验证传进来的是不是接口
- 是否提前将请求接口中的方法缓存对应的服务。
- 动态代理生成对应的代理类。
当执行github.contributors("square", "retrofit")方法时,执行loadServiceMethod(method).invoke(args != null ? args : emptyArgs)这句,看下具体的实现。先看下loadServiceMethod(method),这个是根据传入的方法生成方法的ServiceMethod,并且缓存起来。
ServiceMethod<?> loadServiceMethod(Method method) {
//首次的话,肯定null。
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;
}
继续查看 ServiceMethod.parseAnnotations(this, method);
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);//1
//方法返回的类型
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);//2
}
abstract @Nullable T invoke(Object[] args);
}
- 1处主要是根据传入的方法,解析方法和方法注解,用来以后配置一个requet。
- 2处是获得HttpServiceMethod对象。
看下HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)
/**
* 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
CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method); // 1
//获取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.");
}
//构建Resoponseconverter对象
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
}
注意1处和2处,1处的作用的是将response 转换为需要的类型,2处是生成一个ServiceMethod对象。
然后在看前面代理模式中的
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
也就是调用HttpServiceMethod的invoke()方法,在看HttpServiceMethod中的invoke()方法。
...
@Override ReturnT invoke(Object[] args) {
return callAdapter.adapt(
new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
}
实际是调用的1处的Calladapter里的adapt()方法,现在我们看看1处的生成过程。
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
Retrofit retrofit, Method method) {
Type returnType = method.getGenericReturnType();
Annotation[] annotations = method.getAnnotations();
try {
// noinspection unchecked
// DefaultCallAdapterFactory
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生成的,然后再在retrofit中查看
/**从callAdapterFactories 集合中根据returnType 得到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);
}
/** CompletableFutureCallAdapterFactory
* 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) {
checkNotNull(returnType, "returnType == null");
checkNotNull(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); // 3
if (adapter != null) {
return adapter;
}
}
....
}
最终会根据callAdapterFactories 来生成对象的CallAdapter对象,callAdapterFactories 在retrofit.build()时初始化
public Retrofit build() {
...
// callAdapter集合
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
...
}
现在platform 是java环境默认有俩个
@Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
List<CallAdapter.Factory> factories = new ArrayList<>(2);
factories.add(CompletableFutureCallAdapterFactory.INSTANCE);
factories.add(new DefaultCallAdapterFactory(callbackExecutor));
return unmodifiableList(factories);
}
所以在执行3的时候callAdapterFactories中会有2中实例,而最终根据返回类型我们是在DefaultCallAdapterFactory中得到匹配的CallApater实例。
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
...
@Override public @Nullable CallAdapter<?, ?> get(
...
//SkipCallbackExecutor 是否是annotations中的一个实例
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) {
//这里 executor = null;
return executor == null
? call
: new ExecutorCallbackCall<>(executor, call); //4
}
};
}
...
}
注意到4处也就是我们动态代理中的实际的返回 loadServiceMethod(method).invoke(args != null ? args : emptyArgs);最终得到的就是call 。
整理下流程:

现在我们知道SimpleService中的Call<List<Contributor>> call = github.contributors("square", "retrofit");
call 对象实际就是OkHttpCall类了。OkHttpCall实现了Call接口,在调用SimpleService中的 call.execute().body();其实也就是调用的OkhttpCall中的execute()方法。OkHttpCall中有异步和同步的调用,异步调用的是用enqueue(final Callback<T> callback)方法,现在用的是同步请求execute()。看下具体的实现:
@Override public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
//如果当前已经执行了 则抛出异常。
if (executed) throw new IllegalStateException("Already executed.");
//修改操作状态
executed = true;
//是否有异常产生
if (creationFailure != null) {
if (creationFailure instanceof IOException) {
throw (IOException) creationFailure;
} else if (creationFailure instanceof RuntimeException) {
throw (RuntimeException) creationFailure;
} else {
throw (Error) creationFailure;
}
}
call = rawCall;
if (call == null) {
try {
//创建原生的Call
call = rawCall = createRawCall();
} catch (IOException | RuntimeException | Error e) {
throwIfFatal(e); // Do not assign a fatal error to creationFailure.
creationFailure = e;
throw e;
}
}
}
//如果取消则,则请求取消连接
if (canceled) {
call.cancel();
}
//解析Response
return parseResponse(call.execute());
}
- 首先是判断这个请求是否已经发送。
- 判断是否有异常产生。
- 创建并通过OkHttpClient发送请求。
- 解析Response数据。
整个Retrofit创建到发送请求的,以及接收数据的流程就已经走完了。
不知道有没有觉察到,为什么我们获取的是json这种格式的数据,但解析出来的就是Call<List<Contributor>>这种java格式呢? 下面来看看这个问题。
首先我们来看看我们是如何来解析Response数据的。在OkHttpCall中
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
...
try {
//将rawBody转换为对应的 java对象
T body = responseConverter.convert(catchingBody);
//构建新的Response对象
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;
}
}
注意这个responseConverter也就是在这里将json格式转换为我们需要的格式。responseConverter 的生成是在OkHttpCall的构造器中生成的,经过系列的跟踪,发现responseConverter实例是在Retrofit中生成
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
...
int start = converterFactories.indexOf(skipPast) + 1;
for (int i = start, count = converterFactories.size(); i < count; i++) {
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
if (converter != null) {
//noinspection unchecked
return (Converter<ResponseBody, T>) converter;
}
}
...
}
而converterFactories集合中有我们构造retrofit在实例时传递的GsonConverterFactory.create()实例,所以最终responseConverter的是在GsonConverterFactory中生成。
public final class GsonConverterFactory extends Converter.Factory {
....
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
...
}
现在最主要涉及的就是TypeToken.get(type) type参数的传递的是什么内容了,最终我们发现type的生成是在DefaultCallAdapterFactory中
@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>");
}
//根据ParameterizedType 返回参数的范型类型
// 假如 返回参数类型 returnType 是Call<List<Contributor>> 那么返回的参数类型的范型就是 Type = List<Contributor>,只是第一层泛型
//假如 返回参数类型 returnType 是Contributor 那么没有参数类型的范型 就会报错
final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
//SkipCallbackExecutor 是否是annotations中的一个实例
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) {
//这里 executor = null;
return executor == null
? call
: new ExecutorCallbackCall<>(executor, call);
}
};
}
传递是通过HttpServiceMethod.回调的进行的。
*/
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
...
//获取method方法 返回参数的泛型表达
Type responseType = callAdapter.responseType();
...
}
所以这个reponseType是在方法定义时已经定义好了的 Call<List<Contributor>>,通过Gson将json格式转化为我们需要的Java对象。
public interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
Call<List<Contributor>> contributors(
@Path("owner") String owner,
@Path("repo") String repo);
}
所以整个将json解析成java对象的流程也执行流程也完了。
对我们来说,那么Retrofit有什么好处呢?
- 更好的封装了请求,利于管理,将所有的请求都放在同一个接口文件中,不管是删除,添加,修改都很方便。
- 通过RequetFactory 封装请求的Request。
- Retrofit结合Okhttp使用,基本将OKhttpclient的各种好处都集成过来(支持https,缓存,连接池,自动重连,重定向等)。结合okhttpclient让我们不用花太多时间在网络层面,将更多精力放在业务层面。
- 封装数据转换,自动可以将json格式数据自动转换为java对象。
- CallAdapter 的设计有点巧妙。
- 还有一个问题Retrofit 在Android中要进行线程切换 ,可以配合Rxjava来使用。
- Retrofit的外观模式是指在
retrofit.create()中,为子系统一组接口中提供一个统一的接口访问。