Retrofit
Retrofit设计模式
动态代理,装饰模式,建造者模式,抽象工厂模式,适配器模式
建造者模式创建Retrofit对象。
Retrofit retrofit = new Retrofit.Builder().baseUrl(builder.getHostIp())
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)//Retrofit客户端设置为OkHttpClient
.build();
1.动态代理
Retrofit#create方法负责创建一个动态代理对象。
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
return (T) Proxy.newProxyInstance(service.getClassLoader(),
new Class<?>[] { service }, new InvocationHandler() {
//该对象传入$Proxy0的构造方法中
private final Platform platform = Platform.get();
@Override
public Object invoke(Object proxy, Method method, Object... args)
throws Throwable {
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
利用注解来描述一个Http请求,抽象成Java接口,然后利用反射和动态代理创建service代理对象。Class<?>[]接口数组只有一个元素service。
service服务API
@POST("app.do?")
Call<ServerTimeResponse> getTime(@Query("app_code") String appCode,
@Query("pattern") String pattern);
利用代理对象访问service接口API的interface方法,最后都会调用InvocationHandler#invoke方法。
生成代理对象
通过抽象接口生成代理。
Proxy#newProxyInstance方法。
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler invocationHandler)
throws IllegalArgumentException {
if (invocationHandler == null) {
throw new NullPointerException("invocationHandler == null");
}
Exception cause;
try {
return getProxyClass(loader, interfaces)
.getConstructor(InvocationHandler.class)
.newInstance(invocationHandler);
} catch (NoSuchMethodException e) {
...
} catch (IllegalAccessException e) {
} catch (InstantiationException e) {
} catch (InvocationTargetException e) {
}
}
触发getProxyClass方法,返回Class<?>对象,然后newInstance方法创建实例。
Proxy#getProxyClass方法。
public static Class<?> getProxyClass(ClassLoader loader,
Class<?>... interfaces)
throws IllegalArgumentException {
final List<Class<?>> interfaceList =
new ArrayList<Class<?>>(interfaces.length);
...
synchronized (loader.proxyCache) {
Class<?> proxy = loader.proxyCache.get(interfaceList);
if (proxy != null) {
return proxy;
}
}
...
List<Method> methods = getMethods(interfaces);
Collections.sort(methods, ORDER_BY_SIGNATURE_AND_SUBTYPE);
...
String baseName = commonPackageName != null && !commonPackageName.isEmpty()
? commonPackageName + ".$Proxy"
: "$Proxy";
Class<?> result;
synchronized (loader.proxyCache) {
result = loader.proxyCache.get(interfaceList);
if (result == null) {
String name = baseName + nextClassNameIndex++;
result = generateProxy(name, interfaces, loader, methodsArray, exceptionsArray);
loader.proxyCache.put(interfaceList, result);
}
}
return result
}
1:getProxyClass方法根据interfaces数组,在缓存中查找代理类Class<?> proxy,若找到返回。
2:查找interfaces接口数组的方法,Method排序,增加equal,toString,hashCode三个方法。generateProxy是native方法,根据name,interfaces数组和Methods生成代理类$Proxy0。
3:代理类Class<?>继承Proxy,且实现了interface的方法,具有Proxy与interface两重属性,最后将Class<?>存储在proxyCache缓存中。
4:$Proxy0创建完成后,查找$Proxy0中有InvocationHandler参数的构造器Constructor,利用newInstance方法创建$Proxy0对象。
创建的代理对象是虚拟机运行时动态生成的一个对象。命名方式以$开头,Proxy和数字。
protected Proxy(InvocationHandler h) {
this.h = h;
}
在$Proxy0构造方法中传入了一个InvocationHandler对象,就是在Retrofit#create中new的那个对象InvocationHandler。
用户利用$Proxy0中的interface方法实现Http访问。
路由到InvocationHandler#invoke方法
$Proxy0类生成的interface方法触发super.h.invoke方法,所有的方法都会进入InvocationHandler#invoke方法($Proxy0类反编译可查看)。
在Retrofit#create实现,入参代理对象,interface方法的Method和args参数,解析成Call返回。
动态代理这一套固定的代码可以无侵入的扩展各种Service服务API,基本逻辑是创建一个具有API接口属性的Proxy子类,实现API的方法触发引入了InvocationHandler对象invoke。
2.适配对接okhttp3
Retrofit的对接okhttp3ServiceMethod对象
private final Map<Method, ServiceMethod> serviceMethodCache =
new LinkedHashMap<>();
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;
}
每个service接口服务方法创建ServiceMethod对象,存储在一个serviceMethodCache缓存中,防止每次调用服务方法都创建一个对象,ServiceMethod负责解析Method。
回到InvocationHandler#invoke方法,返回的Object是Call<?>。
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
CallAdapter<?>适配器与工厂
ServiceMethod的Call适配器CallAdapter<?>接口。
public interface CallAdapter<T> {
Type responseType();
<R> T adapt(Call<R> call);
//创建CallAdapter的工厂
abstract class Factory {
public abstract CallAdapter<?> get(Type returnType, Annotation[] annotations,
Retrofit retrofit);
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
Factory工厂创建适配器,Retrofit#nextCallAdapter方法。
public CallAdapter<?> nextCallAdapter(...) {
..
CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
...
}
Retrofit工厂初始化
Retrofit build()方法
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
默认工厂ExecutorCallAdapterFactory,继承CallAdapter.Factory,创建CallAdapter,适配的Call是ExecutorCallbackCall。
ExecutorCallAdapterFactory#get方法,创建一个CallAdapter,adapt适配方法。
@Override
public CallAdapter<Call<?>> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
...
return new CallAdapter<Call<?>>() {
@Override
public Type responseType() {
return responseType;
}
@Override
public <R> Call<R> adapt(Call<R> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
ExecutorCallbackCall实现Retfofit#Call接口,adapt的入参是OkHttpCall ,delegate委派模式。
ExecutorCallbackCall与OkHttpCall都实现Retfofit#Call接口,service服务方法返回的Call都是ExecutorCallbackCall对象,真正调用的是OkHttpCall。
ExecutorCallbackCall分析
ExecutorCallbackCall实现Retrofit#Call接口,方法委派给OkHttpCall。
@Override
public void enqueue(final Callback<T> callback) {//Retrofit#Callback
..//delegate是OkHttpCall。
delegate.enqueue(new Callback<T>() {//Retrofit#Callback
@Override public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
if (delegate.isCanceled()) {
callback.onFailure(...);
} else {
//callback是用户传入
callback.onResponse(ExecutorCallbackCall.this, response);
}
}
});
}
@Override public void onFailure(Call<T> call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}
OkHttpCall#enqueue方法创建一个Callback,触发onResponse方法时,callbackExecutor线程池执行任务,callbackExecutor是MainThreadExecutor。
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable r) {
handler.post(r);
}
}
MainThreadExecutor#execute将Runnable发送到主线程消息队列,进一步封装CallBack的主要目的是将请求回调代码路由到主线程。
OkHttpCall#enqueue请求的Callback,就是封装用户传入Callback的对象。
OkHttpCall分析
OkHttpCall实现Retrofit#Call接口,封装okhttp3框架的请求对象,实现方法对接,主要方法包括enqueue,execute,request。
OkHttpCall#enqueue方法,实现okhttp3异步请求。
@Override //Retrofit#Call的方法
public void enqueue(final Callback<T> callback) {//Retrofit的Callback
okhttp3.Call call;
Throwable failure;
call = rawCall;//OkHttp的Call
failure = creationFailure;
...
if (canceled) {
call.cancel();
}
call.enqueue(new okhttp3.Callback() {//okhttp3异步请求
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response<T> 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) {
}
}
...
private void callSuccess(Response<T> response) {
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
}
}
});
}
- 1:rawCall是okhttp3.Call,创建一个OkHttp请求。rawCall#enqueue方法参数是okhttp3的Callback,在okhttp3#Callback回调Retrofit#Callback回调方法。
-
2:****parseResponse方法负责将okhttp3#Response实体解析成Retrofit#Response,利用ServiceMethod提供的toResponse方法实现,关键调用responseConverter#convert方法,
GsonConverter转换器。
ServiceMethod#toResponse方法。
T toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
-
3:创建生产okhttp3.Call的工厂(callFactory)与okhttp3.Call(rawCall)。
OkHttpCall#createRawCall方法
private okhttp3.Call createRawCall() throws IOException {
Request request = serviceMethod.toRequest(args);//解析参数,生产okHttp3#Request
okhttp3.Call call = serviceMethod.callFactory.newCall(request);//通过工厂创建rawCall
...
return call;
}
ServiceMethod#toRequest方法将Method的参数arg转换成一个Http协议的okHttp3#Request请求,arg就是service服务方法的入参。根据Request,okhttp3.Call#Factory工厂负责创建OKhttp3#Call。
创建okhttp3.Call#Factory工厂,Retrofit建造者中的client方法传入OkHttpClient,OKhttpClinent继承okhttp3.Call.Factory。
public Builder client(OkHttpClient client) {
return callFactory(checkNotNull(client, "client == null"));
}
Converter转换
GsonConverterFactory实现Converter.Factory接口,Converter.Factory抽象工厂负责生产三类Converter。ResponseBody,RequestBody,String。
public interface Converter<F, T> {
T convert(F value) throws IOException;
//创建Converter的抽象工厂
abstract class Factory {
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return null;
}
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return null;
}
public Converter<?, String> stringConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return null;
}
}
}
GsonConverterFactory工厂创建Converter<ResponseBody, T> responseConverter,负责转换ResponseBody对象,转换成用户自己定义的实体对象,即service接口方法返回Call<?>中的泛型。然后创建一个Retrofit#Response封装实体。工厂的抽象方法是固定的,子类工厂提供不同的具体实现。
其他扩展,如RxJava,基于Retrofit接口设计,在创建对象时可使用不同的Convert和CallAdapter工厂,耦合性低,实现插件化。
Retrofit retrofit = new Retrofit.Builder().baseUrl(AppEnvConstants.http_ip)
.addConverterFactory(ProtoConverterFactory.create())//不同的Converter工厂
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())//不同的CallAdapter工厂
.build();
总结:Retrofit利用动态代理,根据一组网络请求的接口服务生成一个代理对象,为每一个接口方法生成一个ServiceMethod,主要负责解析接口方法,包括注解与参数等,注解解析成Http访问类型POST/GET等,参数封装成Request。
适配器CallAdapter与抽象工厂设计使Retrofit和okhttp3无缝对接。
任重而道远