retrofit是一种类型安全的HTTP客户端。所谓的类型安全,就是说在运行时不会报类型错误,它会在编译期检查。 要分析它的源码当然是从使用开始说起。在之前的例子中通过Retrofit.create()方法来生成网络请求对象,利用这个对象进行相关的同步或者异步请求。所以从这里开始。
public <T> T create(final Class<T> service) {
//验证是否为接口而且是不继承其他接口的接口
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
//核心就是动态代理,就是创建一个对象,它会代理service(接口)中的每个方法,
//然后把接口中的每个方法通过serviceMethod.callAdapter.adapt(okHttpCall);代替返回相应的结果
//参数一:类加载器,参数二:动态代理代理的是哪些类,参数三
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
//Anddroid的还是Java8、Java7等
private final Platform platform = Platform.get();
@Override public Object invoke(Object proxy, Method method, Object... args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
//如果是Object类自有的方法就直接执行
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);
//call就做了两件事
//一:生成一个真正的OKHTTP的call并且加入请求队列
//二:对返回结果利用之前定义的converter转换后返回给callback
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
//之所以会用adapter的adapt方法主要是为了线程切换(rxjava的转换),这里是把结果切回主线程
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
复制代码
先关方法的含义已经写到注释里了,因为上面这些核心的就是动态代理,它会代理service中的每个方法,既然是代理接口类的每个方法,那么首先是找到方法 loadServiceMethod(method);
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;
}
复制代码
从上面可以看出无非就是之前加载过的话就从缓存中取,没加载过的话就的重新构建并且加入到缓存中。找到方法之后则很自然的要执行这个方法,那就得是OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);通过这步把要执行的方法及参数保存到了OKHTTP的call中,当执行enqueque的时候则真正的用得到的方法和参数请求网络。 在基本使用中,构造完网络请求对象之后,就用这个对象进行实际的网络请求,比如异步的enquue。
@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) {
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<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) {
t.printStackTrace();
}
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callSuccess(Response<T> response) {
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
复制代码
上面代码中最重要的则是 createRawCall() ,也就是创建OKHTTP的call,然后利用这个call调用OKHTTP的enqueque来进行真正的网络请求,同时将返回值返回到callback中。 到这里已经可以拿到网络通信结果了当然是通过 parseResponse(rawResponse) 转换的最终结果,而这个转换则是通过初始化时 addConverterFactory 添加的转换器,为什么不直接返回这个okHttpCall而是还要进行下一步 return serviceMethod.callAdapter.adapt(okHttpCall); 那就得看一下OKHTTP的enqueque做了什么
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
复制代码
OKHTTP的实现类中的enqueue调用了 client.dispatcher().enqueue(),继续看这个enqueque
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
复制代码
从这个理可以看出来如果当前发送请求的数量大于 maxRequests (当前源码数量为64),加入队列待执行,如果没到则执行,而执行的代码可以清楚的看到使用executorService().execute(call)。说明在后台线程池中进行的请求和返回。那么到这里就大致的可以推断出return adatp的作用了,那就是 线程切换 。 直接跟进去发现adapt方法是在接口类中,那么我们直接找它的实现类看看,一共有两个即 ExecutorCallAdapterFactory 和 DefaultCallAdapterFactory ,然后再看这两个类在那儿用的,发现是在下面这个方法中调用的
CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor != null) {
return new ExecutorCallAdapterFactory(callbackExecutor);
}
return DefaultCallAdapterFactory.INSTANCE;
}
复制代码
而这个方法有又是retrofit的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> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
}
复制代码
而在这个方法中我们看到需要向方法中传一个callbackExecutor,而这个executor从字面看就是与平台相关的,那么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);
}
}
}
复制代码
从handler.post我们一下子就豁然开朗了。 大框架已经已经说完了,那么那些注解什么时候用的呢,那就得从构造方法和参数入手了,仔细看一下
ServiceMethod.Builder<>(this, method).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);
}
复制代码
从上面的源码可以看出首先创建了最后一步需要的callAdapter,然后创建ResponseConverter,也就是通常的将结果转化为Gson等的转换器。然后解析方法注解parseMethodAnnotation(annotation);、解析参数注解parseParameter(p, parameterType, parameterAnnotations)。最后生成的请求和返回所需要的全部参数如下
ServiceMethod(Builder<R, T> 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;
}
复制代码