0.前言
Retrofit是一个基于okhttp的网络请求框架,相当于对于okhttp的一次封装,同理,也是square公司出的,square出品,必属精品,最近有时间,分析仪下它的工作流程,
1.基本使用
interface TestService
{
@GET("/")
fun test(): Call<String>
}
class ResponseConvertFactory : Converter.Factory()
{
override fun responseBodyConverter(type: Type?, annotations: Array<out Annotation>?, retrofit: Retrofit?): Converter<ResponseBody, String>?
{
return Converter<ResponseBody, String> {
it.string()
}
}
override fun stringConverter(type: Type?, annotations: Array<out Annotation>?, retrofit: Retrofit?): Converter<*, String>?
{
return super.stringConverter(type, annotations, retrofit)
}
}
val retrofit = Retrofit.Builder().baseUrl("http://www.baidu.com")
.addConverterFactory(ResponseConvertFactory())
.build()
val testService = retrofit.create(TestService::class.java)
val call = testService.test()
call.enqueue(object : Callback<String>
{
override fun onFailure(call: Call<String>?, t: Throwable?)
{
}
override fun onResponse(call: Call<String>?, response: Response<String>?)
{
println("response is ${response?.body()}")
}
})
这是一个简单的异步http get请求,由于只分析流程,由简单的进入就行了,个人认为看代码了解流程和其设计模式才是最重要的,不需要扣的太厉害。
2.Retrofit的创建
Retrofit的创建采用的建造者模式
val retrofit = Retrofit.Builder().baseUrl("http://www.baidu.com")
.addConverterFactory(ResponseConvertFactory())
.build()
直接看Retrofit.Builder的build方法
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<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories =
new ArrayList<>(1 + this.converterFactories.size());
// Add the built-in converter factory first. This prevents overriding its behavior but also
// ensures correct behavior when using converters that consume all types.
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
这里传入了一个CallAdapter.Factory的list,里面的数据是Builder里的calladapter.Factory的list,也就是你在addCallAdapterFactory()方法中传入的参数,这里传入的factory会放入builder的calladapter.Factory的list里,然后又放入了一个默认的calladapterfactory,这个factory是platform的参数,而这个platform是在实例化Builder的时候传入的
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();
}
如果是跑在android系统,那么返回的就会是Android,看一Android
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);
}
}
}
可以看到platform返回的CallAdapterFactory就是ExecutorCallAdapterFactory。关于他的作用稍后再谈。
还有一个Convert.Factory的list,这里是先加入了一个BuiltInConverters,然后放入存在Builder里的Convert.Factory的list,Convert.Factory主要是用来生成Convert来对http请求体和响应报文进行转换。
2.发行请求前的准备
val testService = retrofit.create(TestService::class.java)
val call = testService.test()
通过这两个方法,生成了一个实现TestService接口的实例,调用这个接口的方法返回一个Call。接下来就看看这是怎么做的,如何为接口生成了一个实例,还有怎么生成的Call。
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() {
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<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
});
}
well well,很明显,这是一个动态代理,如果对动态代理不清楚的,可以参考我之前的文章
拆轮子系列--动态代理。通过动态代理实现了一个实现接口的代理类,接下来看InvocationHandler,如果方法不是来自接口而是object的方法,那么就直接调用,如果是来自接口,那么可以看到先生成了一个serviceMethod,看一下loadServiceMethod方法
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,否则就创建一个ServiceMethod,并添加到缓存,还是建造者模式,看一下ServiceMethod.Builder的build方法
public ServiceMethod build() {
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError("'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
if (httpMethod == null) {
throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
if (!hasBody) {
if (isMultipart) {
throw methodError(
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {
throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
+ "request body (e.g., @POST).");
}
}
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
parameterType);
}
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
if (parameterAnnotations == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
if (relativeUrl == null && !gotUrl) {
throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError("Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && !gotField) {
throw methodError("Form-encoded method must contain at least one @Field.");
}
if (isMultipart && !gotPart) {
throw methodError("Multipart method must contain at least one @Part.");
}
return new ServiceMethod<>(this);
}
先看一下createCallAdapter这个方法
private CallAdapter<T, R> createCallAdapter() {
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError("Service methods cannot return void.");
}
Annotation[] annotations = method.getAnnotations();
try {
//noinspection unchecked
return (CallAdapter<T, R>) 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);
}
}
根据method返回值的Type和注解,调用retrofit的callAdapter返回Calladapter,看一下Retrofit的calladapter方法。
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 = callAdapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = callAdapterFactories.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(callAdapterFactories.get(i).getClass().getName());
}
builder.append('\n');
}
builder.append(" Tried:");
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
builder.append("\n * ").append(callAdapterFactories.get(i).getClass().getName());
}
throw new IllegalArgumentException(builder.toString());
}
言简意赅,遍历Retrofit的CallAdapterFactory list,找到符合要求的calladapter就返回,所以还记得calladapterfactory list的顺序吧,默认的calladapterfactory也就是ExecutorCallAdapterFactory是放在最后的,所以如果你在构建Retrofit的时候添加了别的Calladapter,如果符合条件,是会拦截。RxJavaCallAdapterFactory.create()这个眼熟吧,就是因为它最终返回的是Observable而不是Call。其实这个CallAdapter的作用就是讲OkhttpCall转化为其他数据结构,默认的就是将OkhttpCall转换为ExecutorCallbackCall。
再回到build方法
responseConverter = createResponseConverter();
和返回CallAdapter差不多,只不过这是返回的ResponseConvert
接下来
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
遍历方法注解得到相应参数,具体就不说了。
然后又生成了一个OkhttpCall
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
你会发现这个OkhttpCall实现了OkHttp的call接口,看它的enque方法
@Override public void enqueue(final Callback<T> 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) {
throwIfFatal(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) {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
这里就是生成了一个Okhttp的call,然后接着就是okhttp的网络请求流程了,如果okhttp不熟悉可以看我之前的文章拆轮子系列--okhttp3源码分析。
重新回到invaoctaionhandler,最后调用了serviceMethod.adapte方法,
T adapt(Call<R> call) {
return callAdapter.adapt(call);
}
可以看到就是调用了calladapter的adapt方法,前面说了默认的calladapter是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<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
可以看到返回了一个匿名内部类,他的adapt方法实际返回了ExecutorCallbackCall
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> 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<T> 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<T> 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<T> clone() {
return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
}
@Override public Request request() {
return delegate.request();
}
}
可以发现这个也实现了Okhttp的call接口,同时还持有了一个callbackexecutor和之前生成的okhttpcall,可以发现调用它的enqueu方法真正执行网络请求的就是okhttpcall,而这个callbackexecutor实际是
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
很明显,通过这种方式保证了回调结果在主线程。
(盗张图帮助理解)
图片来自
关注我的公众号
网友评论