从字面理解retrofit2就是用于Android和java平台的类型安全可靠的http请求框架。什么是类型安全呢,所谓类型安全就是编译阶段就已经做了类型检查,在程序运行阶段不会报类型错误。
上述文字是官网描述,这里个人再补充一点,retrofit2实际上是对http请求的一个封装,底层还是通过okhttp进行网络请求的,本节只对retrofit2进行源码分析,后续会补充okhttp的源码分析。
1.定义一个java接口以及http请求方法
public interface GitHubService {
@GET("users/{user}/repos")
Call> listRepos(@Path("user") String user);
}
2.构造Retrofit实例,可配置baseUrl
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
. addConverterFactory(GsonConverterFactory.create())
.build();
3.调用Retrofit实例的create方法生成GitHubService接口实例
GitHubService service = retrofit.create(GitHubService.class);
4.调用GitHubService的listRepos方法获取Call对象
Call> repos = service.listRepos("octocat");
5.通过Call对象去获取请求
repos.enqueue(new Callback() {
@Override
public void onResponse(Call> call, Response> response) {
}
@Override
public void onFailure(Call> call, Throwable t) {
}
});
1.先来看看Retrofit的构造方法,看到builder()就知道是构造者模式创建的Retrofi实例,
这里只贴关键部分代码
//使用的平台 Android 或者 java
private final Platform platform;
//用于网络请求的OkHttpClient
private @Nullable okhttp3.Call.Factory callFactory;
//请求服务器的baseUrl地址
private HttpUrl baseUrl;
//数据转换器工厂
private final List converterFactories = new ArrayList<>();
//网络适配器工厂
private final List adapterFactories = new ArrayList<>();
//任务执行器
private @Nullable Executor callbackExecutor;
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
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 adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
这里重点关注callFactory,converterFactories,callFactory,callbackExecutor这几个对象,这里可以看到如果用户不自定callFactory,则new 一个 OkHttpClient对象。通过上述几个对象构造了Retrofit对象。
public Builder client(OkHttpClient client) {
return callFactory(checkNotNull(client, "client == null"));
}
·······················································
if (callFactory == null) {
callFactory = new OkHttpClient();
}
然后我们看下callbackExecutor,通过platform.defaultCallbackExecutor()得到,我们先看看platfor是怎么获取的,platform = Platform.get();
点击get()方法进去,
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();
}
·········
}
可以看到返回PLATFORM,即findPlatform()方法,当Build.VERSION.SDK_INT != 0满足条件时,返回一个新生成的Android对象,否则返回一个Java8对象。再来看看Android类如下,所以 platform.defaultCallbackExecutor()返回的任务执行器实际上就是MainThreadExecutor对象,持有handler属性将异步任务会调到主线程中去。
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
List adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
接下来看看adapterFactories,无论是否自定义CallAdapter.Factory,都会在集合里面添加一个factory,可以看出是一个ExecutorCallAdapterFactory对象,并且将callbackExecutor作为参数传了进去。咱们先不看具体的ExecutorCallAdapterFactory类实现,回到主线代码来。
获取到Retrofit对象以后,执行create方法,点击进去
public T create(final Class service) {
//验证interface接口,这里不贴具体代码了
//1.首先验证是否是接口
//2.验证是否有继承关系,Retrofit不允许此接口有继承关系
Utils.validateServiceInterface(service);
if (validateEagerly) {
//3.提前加载接口中的method
eagerlyValidateMethods(service);
}
//4.动态代理
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, @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);
}
ServiceMethod
这里最关键的第4点动态代理,可以说动态代理就是Retrofit的核心所在,具体动态代理的内容就不这讲了。create方法传入了GitHubService.class参数,这里动态代理的是GitHubService对象。执行这个代理的listRepos方法相当于执行InvocationHandler的invoke方法,这就解释了为什么只写了一个接口,一个方法名,和一些注解以及一些参数就能进行网络请求了,所有这些工作都是在这个invoke方法里做的,所以我们重点看下这个invoke方法。
//如果该方法直接来自Object类,例如equals(),toString()等,则直接调用
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
//默认false
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod serviceMethod =
(ServiceMethod) loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
我们先看看loadServiceMethod这个方法,先去缓存里取,如果有则返回,没有则生成一个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 = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
我们可以先偷看看这个ServiceMethod类
private final HttpUrl baseUrl;
private final Converter responseConverter;
private final String httpMethod;
private final String relativeUrl;
private final Headers headers;
private final MediaType contentType;
private final boolean hasBody;
private final boolean isFormEncoded;
private final boolean isMultipart;
private final ParameterHandler>[] parameterHandlers;
ServiceMethod(Builder builder) {
this.callFactory = builder.retrofit.callFactory();
this.callAdapter = builder.callAdapter;
this.baseUrl = builder.retrofit.baseUrl();
this.responseConverter = builder.responseConverter;
this.httpMethod = builder.httpMethod;
this.relativeUrl = builder.relativeUrl;
this.headers = builder.headers;
this.contentType = builder.contentType;
this.hasBody = builder.hasBody;
this.isFormEncoded = builder.isFormEncoded;
this.isMultipart = builder.isMultipart;
this.parameterHandlers = builder.parameterHandlers;
}
Request toRequest(@Nullable Object... args) throws IOException {
``````
}
/** Builds a method return value from an HTTP response body. */
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
看到这里,你会不会有种恍然大悟的感觉,httpMethod,relativeUrl,headers…这些参数是不是似曾相识,再看看方法名toRequest,构造一个request请求,toResponse,构造一个reponse响应,所以ServiceMethod类才是retrofit中的重中之重,所有的操作都是通过这个类完成的。
再来看下一行通过serviceMethod,args构造了一个OkHttpCall对象,熟悉动态代理的同学应该知道,这里的args就是接口GitHubService里具体方法的参数数组。同样我们也看下OkHttpCall类,会发现里面有两个很重要的方法,一个是enqueue方法,一个是execute方法,到这里先不看具体实现,回到主线来。
OkHttpCall(ServiceMethod serviceMethod, @Nullable Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
@Override
public void enqueue(final Callback callback) {
............
}
@Override public Response execute() throws IOException {
............
}
继续往下走,这里贴下代码。
return serviceMethod.callAdapter.adapt(okHttpCall);
其中callAdapter对象是在createCallAdapter()方法里返回的,如下
private CallAdapter createCallAdapter() {
//1.获取该方法的返回类型
Type returnType = method.getGenericReturnType();
//2.校验该返回类型是否可处理
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
"Method return type must not include a type variable or wildcard: %s", returnType);
}
//3.判断是void类型
if (returnType == void.class) {
throw methodError("Service methods cannot return void.");
}
Annotation[] annotations = method.getAnnotations();
try {
//noinspection unchecked
return (CallAdapter) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create call adapter for %s", returnType);
}
}
继续往下看
public CallAdapter, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
int start = adapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = adapterFactories.size(); i < count; i++) {
CallAdapter, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
StringBuilder builder = new StringBuilder("Could not locate call adapter for ")
.append(returnType)
.append(".\n");
if (skipPast != null) {
builder.append(" Skipped:");
for (int i = 0; i < start; i++) {
builder.append("\n * ").append(adapterFactories.get(i).getClass().getName());
}
builder.append('\n');
}
builder.append(" Tried:");
for (int i = start, count = adapterFactories.size(); i < count; i++) {
builder.append("\n * ").append(adapterFactories.get(i).getClass().getName());
}
throw new IllegalArgumentException(builder.toString());
}
可以看出CallAdapter主要是由Retrofit里的nextCallAdapter方法生成,从adapterFactories集合中取出一个factory然后调用get方法生成。一开始我们就讲到这个factory如果不自定义的话就是默认自带的ExecutorCallAdapterFactory类,在这里我们看看具体类,
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
final Executor callbackExecutor;
ExecutorCallAdapterFactory(Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
@Override
public CallAdapter, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call adapt(Call call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
............
}
可以看出这里返回了一个匿名类,两个方法,一个是responseType获取请求响应类型,一个是adapt方法,这个adapt方法返回了一个Call对象,具体实现类是ExecutorCallbackCall,我们看下这个类,,,,,等等
咋又出现一个ExecutorCallbackCall类,这类干嘛的,有点懵逼,,,,也有点营养不良
这里有点绕,博主看代码的时候,看到这里经常找不到北,赶紧回到主线,一步一步来
return serviceMethod.callAdapter.adapt(okHttpCall);
我们已经知道 在不自定义的情况下,callserviceMethod.callAdapter获取到的是一个匿名的callAdapter,执行adapt方法,返回了ExecutorCallbackCall对象,这时候再看这个类,
static final class ExecutorCallbackCall implements Call {
final Executor callbackExecutor;
final Call delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override public void enqueue(final Callback callback) {
checkNotNull(callback, "callback == null");
delegate.enqueue(new Callback() {
@Override public void onResponse(Call call, final Response response) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
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 call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}
@Override public boolean isExecuted() {
return delegate.isExecuted();
}
@Override public Response execute() throws IOException {
return delegate.execute();
}
@Override public void cancel() {
delegate.cancel();
}
@Override public boolean isCanceled() {
return delegate.isCanceled();
}
@SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
@Override public Call clone() {
return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
}
@Override public Request request() {
return delegate.request();
}
}
回过头来,终于知道了这个repos对象具体实现就是ExecutorCallbackCall对象
Call> repos = service.listRepos("octocat");
继续往下走通过Call对象去请求,即调用enqueue方法,我们看看这个方法,
@Override public void enqueue(final Callback callback) {
checkNotNull(callback, "callback == null");
delegate.enqueue(new Callback() {
@Override public void onResponse(Call call, final Response response) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
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);
}
}
});
}
这个 delegate就是OkHttpCall对象,不清楚的可以回顾下上面讲的,执行OkHttpCall
的eneque方法,还记不记得上面讲过OkHttpCall 两个重要的方法,现在我们看看OkHttpCall的eneque方法
@Override public void enqueue(final Callback callback) {
checkNotNull(callback, "callback == null");
okhttp3.Call call;
Throwable failure;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
call = rawCall = createRawCall();
} catch (Throwable t) {
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
callSuccess(response);
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callSuccess(Response response) {
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
到这里相信眼睛锐利的网友们可以已经察觉真相,慢慢浮出水面了。。
在这里new了一个okhttp3.Call,并且执行okhttp3.Call的enqueue方法,鼓掌。。。
还没完,我们再看看如何生成okhttp3.Call对象的,
private okhttp3.Call createRawCall() throws IOException {
Request request = serviceMethod.toRequest(args);
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
是不是很眼熟,之前讲ServiceMethod类的时候提到过这个方法toReques(),最初转换成
Okhttp里的Request对象,然后通过Request对象newCall一个Call对象,我们看下这个newCall方法,
interface Factory {
Call newCall(Request request);
}
是个接口,我们看下具体实现,
@Override
public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
还没完,请求看完了,响应呢,我们看看parseResponse方法,
Response parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
// Remove the body's source (the only stateful object) so we can pass the response along.
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
if (code == 204 || code == 205) {
rawBody.close();
return Response.success(null, rawResponse);
}
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
T body = serviceMethod.toResponse(catchingBody);
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;
}
}
又看到了一个熟悉的背影,serviceMethod.toResponse(catchingBody),看下具体实现
/** Builds a method return value from an HTTP response body. */
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
可以看出ServiceMethod对象将ResponseBody对象转换成用户定义的类型对象,其中 responseConverter来自Retrofit对象中的converterFactories集合,
public Converter nextResponseBodyConverter(
@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
checkNotNull(type, "type == null");
checkNotNull(annotations, "annotations == null");
int start = converterFactories.indexOf(skipPast) + 1;
for (int i = start, count = converterFactories.size(); i < count; i++) {
Converter converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
if (converter != null) {
//noinspection unchecked
return (Converter) converter;
}
}
StringBuilder builder = new StringBuilder("Could not locate ResponseBody converter for ")
.append(type)
.append(".\n");
if (skipPast != null) {
builder.append(" Skipped:");
for (int i = 0; i < start; i++) {
builder.append("\n * ").append(converterFactories.get(i).getClass().getName());
}
builder.append('\n');
}
builder.append(" Tried:");
for (int i = start, count = converterFactories.size(); i < count; i++) {
builder.append("\n * ").append(converterFactories.get(i).getClass().getName());
}
throw new IllegalArgumentException(builder.toString());
}
同样如果用户没有定义会有一个默认的转换工具BuiltInConverters,responseBodyConverter方法将ResponseBody对象转换成用户定义的类型对象
final class BuiltInConverters extends Converter.Factory {
@Override
public Converter responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
if (type == ResponseBody.class) {
return Utils.isAnnotationPresent(annotations, Streaming.class)
? StreamingResponseBodyConverter.INSTANCE
: BufferingResponseBodyConverter.INSTANCE;
}
if (type == Void.class) {
return VoidResponseBodyConverter.INSTANCE;
}
return null;
}
.........
}
回到主线来,快接近尾声了,parseResponse方法返回后,执行callSuccess方法,
private void callSuccess(Response response) {
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
注意这里的callback并不是用户自定义的callback,而是OkhttpCall的execute方法的入参,执行 callback.onResponse(OkHttpCall.this, response),callbackExecutor将异步任务结果抛到主线程中去,然后这里的callback就是我们一开始repos.enqueue方法传进来的回调,会在主线中执行。
delegate.enqueue(new Callback() {
@Override public void onResponse(Call call, final Response response) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
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 call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
到这里就算读完整个Retrofit框架流程了,其实还有很多细节,在这里就不一一讲了。
另外,作为一名技术人员,一定要做到知其然知其所以然。
1.对于一个框架使用,要清晰的知道它是干嘛的。
2.了解它的使用方式,了解它的常用的api
3.研究源码,设计流程和结构。
Thanks~*