使用Retrofit作为Android网络请求已经非常普遍了,并且Retrofit的源码不仅少而且还很精妙,作为阅读学习的对象在合适不过了。虽然很久之前就用了,但是还真没看过源码,趁着最近空闲就试着看看把。本文Retrofit版本是 2.6.0。看完我觉得还是2.4之前会更轻松点吧,可惜我没找到老版本的jar包
基本用法
要了解一个框架的源码,肯定要知道它的基本用法。然后从基本用法里选择一个入口方法,这样就可以跟着用法读下去了。
1、定义请求接口
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<UserBean>> listRepos(@Path("user") String user);
}
2、初始化Retrofit
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.client(new OkHttpClient())
//.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
GitHubService service = retrofit.create(GitHubService.class);
3、网络请求
Call<List<UserBean>> repos = service.listRepos("octocat");
{
repos.enqueue(new Callback<List<UserBean>>() {
@Override
public void onResponse(Call<List<UserBean>> call, Response<List<UserBean>> response) {
List<UserBean> list = response.body();
}
@Override
public void onFailure(Call<List<UserBean>> call, Throwable throwable) {
}
});
}
源码阅读
从上面3个使用步骤我们可以很明显的看出retrofit.create()
是一个入口方法,首先先来看看Retrofit()中都初始化了啥。
一、Retrofit初始化
Retrofit通过Builder设计模式进行初始化。看一下build()
方法中都做了些什么。
public Retrofit build() {
//初始化时baseUrl是必须的
if(this.baseUrl == null) {
throw new IllegalStateException("Base URL required.");
} else {
Object callFactory = this.callFactory;
//初始化时如果没有设置client,callFactory 为null
//默认创建一个OkHttpClient赋值给callFactory
if(callFactory == null) {
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if(callbackExecutor == null) {
callbackExecutor = this.platform.defaultCallbackExecutor();
}
//调用addCallAdapterFactory时初始化
//如果没有初始化,使用DefaultCallAdapterFactory
ArrayList callAdapterFactories = new ArrayList(this.callAdapterFactories);
callAdapterFactories.addAll(this.platform.defaultCallAdapterFactories(callbackExecutor));
//调用addConverterFactory时候初始化,
//如果没有初始化使用默认的BuiltInConverters
ArrayList converterFactories = new ArrayList(1 + this.converterFactories.size() + this.platform.defaultConverterFactoriesSize());
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(this.platform.defaultConverterFactories());
return new Retrofit((Factory)callFactory, this.baseUrl, Collections.unmodifiableList(converterFactories), Collections.unmodifiableList(callAdapterFactories), callbackExecutor, this.validateEagerly);
}
}
构造Retrofit对象的时候初始化了三个非常重要的参数:
- callFactory
- CallAdapter
- ConverterFactory
1、callFactory ,即OkHttpClient,继承Call.Factory。OKhttp的工厂类
2、CallAdapter。适配器模式,负责将Call对象转换成我们需要的类型。例如Rxjava中的Observable对象。
如下默认login返回Call对象,当时用初始化时调用addCallAdapterFactory(RxJava2CallAdapterFactory.create())
给Retrofit添加一个RxJava的适配器的时候,则返回Observable对象
// 使用默认适配器时
Call<String> login();
// 添加Rxjava适配器时的返回
Observable<String> login();
3、ConverterFactory,转换工厂。将http返回的response转换成我们需要的对象。如UserBean。
二、构建service对象
GitHubService service = retrofit.create(GitHubService.class);
create方法源码如下:
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if(this.validateEagerly) {
this.eagerlyValidateMethods(service);
}
return Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service}, new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Nullable
public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable {
return method.getDeclaringClass() == Object.class?method.invoke(this, args):(this.platform.isDefaultMethod(method)?
this.platform.invokeDefaultMethod(method, service, proxy, args):
Retrofit.this.loadServiceMethod(method).invoke(args != null?args:this.emptyArgs));
}
});
}
Create方法中完成了两件事情:
1、使用代理模式动态创建一个Service对象并返回
2、创建ServiceMethod对象,并且调用invoke()方法。
关于动态代理和反射可以我的另外两篇文章:
代理模式
Java反射机制
创建ServiceMethod对象
通过loadServiceMethod()方法获得一个ServiceMethod。
ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod result = (ServiceMethod)this.serviceMethodCache.get(method);
if(result != null) {
return result;
} else {
Map var3 = this.serviceMethodCache;
synchronized(this.serviceMethodCache) {
result = (ServiceMethod)this.serviceMethodCache.get(method);
if(result == null) {
result = ServiceMethod.parseAnnotations(this, method);
this.serviceMethodCache.put(method, result);
}
return result;
}
}
}
可以看到loadServiceMethod()方法中有个会对ServiceMethod对象进行缓存,当ServiceMethod对象为null时,会调用ServiceMethod.parseAnnotations(this, method)
获得一个ServiceMethod对象。
abstract class ServiceMethod<T> {
ServiceMethod() {
}
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
Type returnType = method.getGenericReturnType();
if(Utils.hasUnresolvableType(returnType)) {
throw Utils.methodError(method, "Method return type must not include a type variable or wildcard: %s", new Object[]{returnType});
} else if(returnType == Void.TYPE) {
throw Utils.methodError(method, "Service methods cannot return void.", new Object[0]);
} else {
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
}
@Nullable
abstract T invoke(Object[] var1);
}
从上面源码可以看出ServiceMethod是一个抽象类。通过parseAnnotations()方法获得一个ServiceMethod对象。
获得RequestFactory
看一下ServiceMethod.parseAnnotations方法,首先会调用RequestFactory.parseAnnotations方法,获得一个RequestFactory 对象
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
那么RequestFactory 又是什么呢?
查看RequestFactory.parseAnnotations源码如下
可以看到RequestFactory又是一个Builder模式。看一下Builder中的参数和方法
从上面的参数不难看出,这其实就是我们基本用法第一步中新建GitHubService 中的请求方法的解析。
@GET("users/{user}/repos")
Call<List<UserBean>> listRepos(@Path("user") String user);
比如解析上面的请求方法GET,路径"users/{user}/repos",参数等等。
下面来看一下有哪些解析方法:
//解析Http请求的方法,get、post等
private void parseMethodAnnotation(Annotation annotation);
//解析Http请求的方法和路径
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody);
//解析请求头
private Headers parseHeaders(String[] headers)
//解析请求参数
private ParameterHandler<?> parseParameter(int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation)
//解析参数中的注解 例如@path。方法内调用ParameterHandler解析
private ParameterHandler<?> parseParameterAnnotation(int p, Type type, Annotation[] annotations, Annotation annotation)
static Set<String> parsePathParameters(String path);
解析方法时有个非常重要的类ParameterHandler,具体的解析是由ParameterHandler来完成的。
现在我们已经知道了RequestFactory的作用了,解析http请求的方法,路径,请求头等和http请求相关的参数了。
继续回到我们的ServiceMethod类中。
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
Type returnType = method.getGenericReturnType();
if(Utils.hasUnresolvableType(returnType)) {
throw Utils.methodError(method, "Method return type must not include a type variable or wildcard: %s", new Object[]{returnType});
} else if(returnType == Void.TYPE) {
throw Utils.methodError(method, "Service methods cannot return void.", new Object[0]);
} else {
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
}
通过反射获得方法的返回类型:
Type returnType = method.getGenericReturnType();
然后调用HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
获得一个HttpServiceMethod对象。
HttpServiceMethod
HttpServiceMethod继承自ServiceMethod。
HttpServiceMethod构造方法如下:
HttpServiceMethod(RequestFactory requestFactory, Factory callFactory, Converter<ResponseBody, ResponseT> responseConverter) {
this.requestFactory = requestFactory;
this.callFactory = callFactory;
this.responseConverter = responseConverter;
}
需要初始化三个非常重要的参数:
- requestFactory :service中的请求参数
- callFactory :Call的适配器
- responseConverter :response转换器
HttpServiceMethod.parseAnnotations()源码如下(有省略):
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(Retrofit retrofit, Method method, RequestFactory requestFactory) {
...
Annotation[] annotations = method.getAnnotations();
Object adapterType;
Type responseType;
...
adapterType = method.getGenericReturnType();
//创建一个Call适配器
CallAdapter callAdapter1 = createCallAdapter(retrofit, method, (Type)adapterType, annotations);
//获得返回类型
responseType = callAdapter1.responseType();
...
//创建一个Converter
Converter responseConverter = createResponseConverter(retrofit, method, responseType);
Factory callFactory = retrofit.callFactory;
return (HttpServiceMethod)(new HttpServiceMethod.CallAdapted(requestFactory, callFactory, responseConverter, callAdapter1);
}
1、创建CallAdapter 对象
跟踪createCallAdapter()方法,最终会调用Retrofit类中的nextCallAdapter()方法。源码如下
public CallAdapter<?, ?> nextCallAdapter(@Nullable retrofit2.CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
Utils.checkNotNull(returnType, "returnType == null");
Utils.checkNotNull(annotations, "annotations == null");
int start = this.callAdapterFactories.indexOf(skipPast) + 1;
int builder = start;
int i;
for(i = this.callAdapterFactories.size(); builder < i; ++builder) {
CallAdapter count = ((retrofit2.CallAdapter.Factory)this.callAdapterFactories.get(builder)).get(returnType, annotations, this);
//获得一个不为null的CallAdapter 并且返回
if(count != null) {
return count;
}
}
...
throw new IllegalArgumentException(var8.toString());
}
nextCallAdapter()方法中遍历callAdapterFactories集合中的CallAdapter,而callAdapterFactories则在Retrofit初始化的时候通过addCallAdapterFactory()赋值或者默认值。
当获得一个不为null的CallAdapter 的时候则返回。
2、创建Converter对象
通过responseType = callAdapter1.responseType();
得到response类型。
通过Converter responseConverter = createResponseConverter(retrofit, method, responseType);
创建一个responseConverter
跟踪createResponseConverter()方法,最终在Retrofit中调用nextResponseBodyConverter()
方法,源码如下:
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(@Nullable retrofit2.Converter.Factory skipPast, Type type, Annotation[] annotations) {
Utils.checkNotNull(type, "type == null");
Utils.checkNotNull(annotations, "annotations == null");
int start = this.converterFactories.indexOf(skipPast) + 1;
int builder = start;
int i;
for(i = this.converterFactories.size(); builder < i; ++builder) {
Converter count = ((retrofit2.Converter.Factory)this.converterFactories.get(builder)).responseBodyConverter(type, annotations, this);
if(count != null) {
return count;
}
}
throw new IllegalArgumentException(var8.toString());
}
同样获得Retrofit初始化时Converter 对象并返回。通过addConverterFactory()方法初始化或者使用默认的Converter 。
3、获得callFactory
通过Factory callFactory = retrofit.callFactory;
获得一个Factory 对象。
同样是在retrofit初始化的时候创建赋值。
4、返回HttpServiceMethod对象
new一个继承自HttpServiceMethod 的 CallAdapted对象
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
private final CallAdapter<ResponseT, ReturnT> callAdapter;
CallAdapted(RequestFactory requestFactory, Factory callFactory, Converter<ResponseBody, ResponseT> responseConverter, CallAdapter<ResponseT, ReturnT> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}
protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return this.callAdapter.adapt(call);
}
}
以上就是HttpServiceMethod类中的主要作用,到此ServiceMethod创建,我们需要再次回到Create()方法中。
创建OkHttpCall 对象
Create方法中完成了两件事情:
1、使用代理模式动态创建一个Service对象并返回
2、创建ServiceMethod对象,并且调用invoke()方法。
上面ServiceMethod对象创建完毕,我们已经获得一个ServiceMethod的实例对象HttpServiceMethod,现在执行HttpServiceMethod对象中的invoke()方法。
源码如下:
final ReturnT invoke(Object[] args) {
OkHttpCall call = new OkHttpCall(this.requestFactory, args, this.callFactory, this.responseConverter);
return this.adapt(call, args);
}
在invoke方法中会创建并初始化一个OkHttpCall 对象,继承Call对象。
三、请求网络
Call<List<UserBean>> call = service.listRepos("octocat");
{
call.enqueue(new Callback<List<UserBean>>() {
@Override
public void onResponse(Call<List<UserBean>> call, Response<List<UserBean>> response) {
}
@Override
public void onFailure(Call<List<UserBean>> call, Throwable throwable) {
}
});
}
1、call.queue()源码
调用ApiService中的请求方法,获得一个Call返回值,通过call.enqueue()
执行网络请求。
Call对象是一个接口,它的实现类是OkHttpCall ,所以真正网络请求逻辑都在OkHttpCall 中
queue()方法源码如下:
public void enqueue(final Callback<T> callback) {
okhttp3.Call call;//声明一个okhttp请求call
Throwable failure;
...//省略一些空判断,空处理
//执行okhttp请求,Retrofit是基于okhttp3进行封装的网络请求框架,
//真正请求网络的部分还是OKhttp
call.enqueue(new okhttp3.Callback() {
//okhttp成功回调
public void onResponse(okhttp3.Call call, Response rawResponse) {
retrofit2.Response response;
try {
//解析成功的数据,返回我们需要的类型
response = OkHttpCall.this.parseResponse(rawResponse);
} catch (Throwable var6) {
Utils.throwIfFatal(var6);
this.callFailure(var6);
return;
}
try {
//外部callback回调
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable var5) {
Utils.throwIfFatal(var5);
var5.printStackTrace();
}
}
//OKhttp失败回调
public void onFailure(okhttp3.Call call, IOException e) {
this.callFailure(e);
}
private void callFailure(Throwable e) {
try {
//外部Callback回调
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable var3) {
Utils.throwIfFatal(var3);
var3.printStackTrace();
}
}
});
}
从源码可以看到,真正执行网络请求的是OKhttp,而当请求成功的时候,okhttp成功回调中有一行很重要的代码:
retrofit2.Response response;
//解析OKhttp返回的rawResponse,转换成我们需要的response
response = OkHttpCall.this.parseResponse(rawResponse);
解析OKhttp成功返回结果
parseResponse()源码如下:
retrofit2.Response<T> parseResponse(Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
rawResponse = rawResponse.newBuilder().body(new OkHttpCall.NoContentResponseBody(rawBody.contentType(), rawBody.contentLength())).build();
int code = rawResponse.code();
if(code >= 200 && code < 300) {
if(code != 204 && code != 205) {
OkHttpCall.ExceptionCatchingResponseBody catchingBody1 = new OkHttpCall.ExceptionCatchingResponseBody(rawBody);
try {
//将Body数据转换成我们需要的类型
Object e1 = this.responseConverter.convert(catchingBody1);
return retrofit2.Response.success(e1, rawResponse);
} catch (RuntimeException var9) {
catchingBody1.throwIfCaught();
throw var9;
}
} else {
rawBody.close();
return retrofit2.Response.success((Object)null, rawResponse);
}
} else {
...//省略
return e;
}
}
这里面也有段非常核心的代码:
Object e1 = this.responseConverter.convert(catchingBody1);
通过 responseConverter 调用 convert 方法实现类型转换。
那么responseConverter 是啥?
responseConverter 是一个Converter对象,负责将ResponseBody 转换成 T 类型。
responseConverter 在哪赋值?
可以看到responseConverter 是在OKhttpCall的构造方法中进行初始化的
OKhttpCall的创建是在调用HttpServiceMethod 的 invoke() 方法中进行创建的,而responseConverter就是在HttpServiceMethod 中通过Converter responseConverter = createResponseConverter(retrofit, method, responseType);
进行创建的。
到此从Retrofit初始化到网络结束已经完成。
因为在Retrofit初始化的时候,初始化了一个 defaultCallbackExecutor。
Executor callbackExecutor = this.callbackExecutor;
if(callbackExecutor == null) {
callbackExecutor = this.platform.defaultCallbackExecutor();
}
而defaultCallbackExecutor 在Android平台源码如下
public Executor defaultCallbackExecutor() {
return new Platform.Android.MainThreadExecutor();
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
MainThreadExecutor() {
}
public void execute(Runnable r) {
this.handler.post(r);
}
}
可以看到这是一个在主线程的回调,所以我们可以直接在Retrofit的callback中进行进行ui操作。
Retrofit流程图:
总结
Retrofit源码阅读到这里了,其实还有不少为什么这样做的问题还没有消化,现在只是知道是这样做这样写的。看之前也是做了些准备的,比如去学习了代理模式,反射,适配器模式,装饰模式等。还好也没准备一口气吃个胖子,慢慢积累,过段时间再来看看会不会好点。