之前学习了怎么使用Retrofit,现在来学习它的原理。Retrofit使用接口+注解的形式来定义一个网络请求,在通过OkHttp来执行网络请求。现在有很多开源使用了注解Annotation,如Dagger2、ButterKnife等,以及Retrofit。所不同的是他们利用注解干的事却不一样。Dagger2、ButterKnife他们在编译期间就处理注解生成代码,提供依赖注入。Retrofit则是则运行期间处理注解,通过动态代理的方式来提供AOP能力。
Retrofit至少使用了5中设计模式:
1)建造者模式
2)动态代理模式
3)静态代理模式
4)适配器模式
5)工厂模式
下面将一步一步来简单分析Retrofit的源码
//使用建造者模式创建Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_URL)
.addConverterFactory(GsonConverterFactory.create()).build();
//创建Github接口对象
Github github = retrofit.create(Github.class);
Call> call = github.getContributors("square", "retrofit");
//设置回调接口,下载任务加入到网络请求队列中,底层调用了OkHttp来完成网络请求
call.enqueue(new Callback>() {...});
这里最核心的过程就是:
Github github = retrofit.create(Github.class);
Call> call = github.getContributors("square", "retrofit");
它使用了动态代理的方式来创建一个网络请求任务,create方法返回了一个动态代理对象github。
Java动态代理就是Java开发给了开发人员一种可能:当你要调用某个类的方法前,插入你想要执行的代码比如你要执行某个操作前,你必须要判断这个用户是否登录,或者你在付款前,你需要判断这个人的账户中存在这么多钱。这么简单的一句话,我相信可以把一个不懂技术的人也讲明白Java动态代理是什么东西了。那么问题来了,我们的接口是Github,但是并未提供Github的实现类,动态代理对象到底代理的是哪个具体类的方法啊?
从下面的代码看出,实际上在动态代理时,并未执行service的method方法,而是在调用invoke方法中另起一套逻辑,这就是AOP编程的精髓,横切一刀插入自己的代码,这也是为啥只需要提供一个接口就OK的原因!当然Retrofit也留了一手,你可以定义一个实现了Github接口的类,这样动态代理时调用的方法就是自己定义的方法。
public T create(final Class service) {
Utils.validateServiceInterface(service);//判断接口是否非法
if (validateEagerly) {
eagerlyValidateMethods(service);
}
//Retrofit最核心的代码,通过动态代理的方式来创建一个继承了Github接口的实现类
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, Object... args)
throws Throwable {
//如果service类已经实现了Github接口,则不会调用service类中的方法
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//创建ServiceMethod对象
ServiceMethod serviceMethod = loadServiceMethod(method);
//创建OkHttpCall对象,该对象内部维护了OkHttp的RealCall对象
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
//返回Call>对象,这句代码不简单,采用了工厂模式、静态代理和适配器模式
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
//ServiceMethod是个什么东西,将接口方法转换成一个HTTP Call
ServiceMethod loadServiceMethod(Method method) {
ServiceMethod result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);//缓存机制
if (result == null) {
result = new ServiceMethod.Builder(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
下面来看看serviceMethod.callAdapter.adapt(okHttpCall)这句代码后面的设计模式
ExecutorCallAdapterFactory为工厂类,创建CallAdapter对象
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);
//返回CallAdapter对象
return new CallAdapter>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call adapt(Call call) {
//返回代理类
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;//主线程执行器MainThreadExecutor,调用主线程Handler分发事件
final Call delegate;//被代理的对象,即我们的okhttpcall对象
ExecutorCallbackCall(Executor callbackExecutor, Call delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override public void enqueue(final Callback callback) {
if (callback == null) throw new NullPointerException("callback == null");
//调用被代理对象的enqueue方法,这里是okhttpcall类,处理结果通过callbackExecutor返回给主线程调用
delegate.enqueue(new Callback() {
@Override public void onResponse(Call call, final Response 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 call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}
...
}
}
上文提到的ExecutorCallAdapterFactory和MainThreadExecutorAndroid类为Retrofit提供的默认实现,当然我们可以自己定义相应的类来覆盖默认实现。这些默认实际上是由一个叫Platform的类提供的,在Android平台上,使用的一个叫做Android的类,它这个继承自Platform,定义了默认的CallAdapterFactory和默认的Executor
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
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);
}
}
}
new ServiceMethod.Builder(this, method).build()背后做了啥?ServiceMethod也采用了建造者模式来创建ServiceMethod对象。
public Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();//反射获取注解
this.parameterTypes = method.getGenericParameterTypes();//反射获取参数类型
this.parameterAnnotationsArray = method.getParameterAnnotations();//反射获取参数的注解
}
public ServiceMethod build() {
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
...
}
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);//处理方法的注解
}
...
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
...
}
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
if (parameterAnnotations == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
//处理参数的注解
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
...
return new ServiceMethod<>(this);
}
将任务传递给OkHttp处理
public void enqueue(final Callback callback) {
...
//引入了OkHttp
okhttp3.Call call;
Throwable failure;
//同时只能允许一个Request存在
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
call = rawCall = createRawCall();//创建OkHttp请求对象RealCall
} 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 {
...
callback.onResponse(OkHttpCall.this, response);
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
...
callback.onFailure(OkHttpCall.this, e);
}
});
}
private okhttp3.Call createRawCall() throws IOException {
//构建一个HTTP请求
Request request = serviceMethod.toRequest(args);
//相当于调用了new OkHttpClient().newCall(request),创建一个OkHttp Call
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
在Retrofit的默认实现中,CallBack回调运行在主线程上,而不用管retrofit是否是在主线程中调用。
1)因为Retrofit底层调用的是OkHttp,而OkHttp的回调并非运行在主线程,所以Retrofit对它进行了封装,使用主线程Handler进行分发,使得CallBack回调运行在主线程上
2)也就说不管在哪个线程中调用retrofit,我们都可以在Retrofit的回调中直接操作UI,这个特性是不是很屌!
public class MainActivity extends AppCompatActivity {
public static final String API_URL = "https://www.baidu.com";
private TextView text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text=(TextView)findViewById(R.id.text);
new Thread(new Runnable() {
@Override
public void run() {
//子线程中使用retrofit
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_URL)
.addConverterFactory(GsonConverterFactory.create()).build();
Github github = retrofit.create(Github.class);
Call> call = github.getContributors("square", "retrofit");
call.enqueue(callback);
}
}).start();
}
private Callback> callback=new Callback>() {
@Override
public void onResponse(Call> call, Response> response) {
//直接进行UI操作,是OK的
text.setText("contributor");
}
@Override
public void onFailure(Call> call, Throwable t) {
Log.e("contributor number", "failure");
}
};
}