清新一刻
生活有时就是这么残酷,可能没人关心你的努力,大家只看最后的结果。成年人的世界没有“容易”二字!所谓无心插柳,都是努力后的水到渠成。
背景
相信现在Android在做网络方面的内容时,首先想到的就是Retrofit。为什么呢?
我这里总结了两条原因:
1、OkHttp用其强大的功力成功打入Android框架内部,(对于OkHttp还不太熟悉的朋友,建议先去了解一下,如果想对它的内部代码了解的,请看OKhttp源码系列文章)
2、Retrofit就是对Okhttp的再封装,加上其通过注解的方式设计API并构造请求报文。完美的体现了简单易用,功能强大八个字。
正文
今天准备搞一搞Retrofit的执行器 —— OkHttpCall。顾名思义,执行器就是要来执行请求的,执行的方式有两种:
①同步执行;
②异步执行
这两种执行方式也是我们今天主要的分析内容,通过分析执行方式来了解Retrofit的执行器和Okhttp的执行器有什么关系。
在分析的过程中我会省略部分代码,目的是便于查看主要分析内容。
先来看一下Retrofit的基本用法
第一步、定义请求接口
public interface RequestInterface {
@GET("/login/login")
Call<ResponseBody> getMethod(@Field("username") String userName, @Field("password") String password);
}
第二步、实例化请求接口
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(sBaseUrl)
.build();
RequestInterface requestInterface = retrofit.create(RequestInterface.class);
第三步、执行请求
Call<ResponseBody> call = requestInterface .getMethod("","");
try {
Response response = call.execute();//执行同步请求
} catch (IOException e) {
e.printStackTrace();
}
/*执行异步请求*/
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
现在需要找到分析源码的入口,第一步就是定义一个接口,没什么东西。第二步实例化Retrofit并通过.create(class )得到接口对象。都知道接口是不能实例化对象的,那么这里是怎么做的呢?跟进去看看
public <T> T create(final Class<T> service) {
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
@Override public Object invoke(Object proxy, Method method, Object... args)
throws Throwable {
ServiceMethod serviceMethod = loadServiceMethod(method);
// 看这里!!! ,OkHttpCall。 就是我们要分析的执行器
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
动态代理!原来是通过动态代理的方式去实例化接口对象。大家可以看上面我加注释的地方,就是Retrofit执行器的部分。那我们看看这个类的内部是怎样的。
final class OkHttpCall<T> implements Call<T> {
private volatile boolean canceled;//执行器是否被取消执行
private okhttp3.Call rawCall; //这是真正的执行器
private boolean executed; // 执行器是否正在执行
/*复写克隆方法,实例化新的OkHttpCall执行器*/
@Override public OkHttpCall<T> clone() {
return new OkHttpCall<>(serviceMethod, args);
}
/*异步执行*/
@Override public void enqueue(final Callback<T> callback) {
okhttp3.Call call;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true; // 标识该执行器正在执行
call = rawCall; // 得到OkHttp.call
if (call == null) {
try {
call = rawCall = createRawCall(); //如果为空就创建OkHttp.call
} catch (Throwable t) {
failure = creationFailure = t;
}
}
}
if (failure != null) { // OkHttp.call 构造失败
callback.onFailure(this, failure);
return;
}
if (canceled) { // 用户取消了执行器的执行
call.cancel(); //去执行OkHttp.call 的取消行为
}
//OkHttp.call 真正的执行过程
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
callback.onResponse(OkHttpCall.this, 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();
}
}
});
}
/*同步执行*/
@Override public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = rawCall;
if (call == null) {
try {
call = rawCall = createRawCall();
} catch (IOException | RuntimeException e) {
creationFailure = e;
throw e;
}
}
}
if (canceled) {
call.cancel();
}
return parseResponse(call.execute());
}
上面的代码我省略了很多,今天只抓主要内容。通过上面的规整,相信对OkHttp有过了解的朋友(没有了解过的朋友,请参看这篇文章OkHttp3源码(八) —— RealCall ),一眼就看出来了,OkHttpCall其实就是对OkHttp中RealCall的封装。将对OkHtpCall相关方法的调用(主要是execute()和enqueue(callback)两个方法)转交给OkHttp的RealCall相关方法。如果你对OkHttp的RealCall有过了解,那么到现在就对Retrofit执行器的源码分析完啦。 哈哈哈。。。。 是不是超简单。
这里OkHttpCall实现了Call接口,这个接口也很简单,就是定义了执行器的主要方法,看一下内容:
public interface Call<T> extends Cloneable {
Response<T> execute() throws IOException;
void enqueue(Callback<T> callback);
boolean isExecuted();
void cancel();
Request request();
}
对于OkHttpCall今天就分析到这里,一句话总结:
OkHttpCall就是对OkHttp的RealCall的封装,最终执行都要OkHttp的RealCall来完成。所以对OkHttp的RealCall不了解的强烈建议去看
OkHttp3源码(八) —— RealCall
最后一问
我们回头再看看请求接口的定义,大家有没有想过,请求接口中方法的返回值到底是怎么来的,它必须是Call类型嘛?实际类型参数必须是ResponseBody嘛?
public interface RequestInterface {
@GET("/login/login")
Call<ResponseBody> getMethod(@Field("username") String userName, @Field("password") String password);
}
对于这个问题的答案我会在下篇博文中给出,相信看完下篇博文后,你会恍然大悟,原来与此。。。。。。