Retrofit源码分析
前言
retrofit是基于okhttp3的(推荐先看OkHttp3源码解析),没图说个jb?下面附图一张(感谢这是一份很详细的 Retrofit 2.0 使用教程(含实例讲解)这篇博客友情提供); 接着我会用一个简单的实例,进行源码的分析以及讲解。
实例
导入一些必要的第三方库
compile 'com.squareup.retrofit2:retrofit:2.3.0' compile 'com.squareup.retrofit2:converter-gson:2.3.0' compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
接着创建ServiceInterface(动态代理接口)
public interface TestApi {
@GET("data/福利/{number}/{page}")
Call<GankBeautyResult> getBeauties(@Path("number") int number, @Path("page") int page);
}
3.请求实例
Retrofit retrofit = new Retrofit.Builder()
.client(new OkHttpClient())
.baseUrl("http://gank.io/api/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
TestApi testApi = retrofit.create(TestApi.class);
Call<GankBeautyResult> call = testApi.getBeauties(100, 1);
call.enqueue(new Callback<GankBeautyResult>() {
@Override
public void onResponse(Call<GankBeautyResult> call, Response<GankBeautyResult> response) {
System.out.println("response content:" + response.body().beauties.size());
}
@Override
public void onFailure(Call call, Throwable t) {
}
});
实例源码分析
初始化retrofit实例
根据实例代码,通过建造者模式创建一个retrofit实例如下;其中baseUrl属性是必须指定的;由1行,Retrofit.Builder()实例方法首先通过Platform的静态方法get()得到Android实例(通过18-57行),然后调用重载方法Builder(Platform);由2-4行,一些参数的赋值;由5行,由60-62行,baseUrl属性是必须指定的;由64-67行,如果没有指定OkHttpClient,那么就创建一个OkhttpClient;由69-72行,通过刚刚得到的Android实例获取callbackExecutor;由75-79行,一些CallAdapter和Converter的保存,最后把上述传入创建Retrofit对象。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://gank.io/api/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
public Builder() {
this(Platform.get());
}
Builder(Platform platform) {
this.platform = platform;
// 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());
}
static Platform get() {
return PLATFORM;
}
private static final Platform PLATFORM = findPlatform();
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();
}
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);
}
}
}
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);
}
代理代理(接口的代理)
由1行,通过动态代理,生成代理对象testApi; 动态代理的原理自行Google,当调用该代理对象的方法时,会执行内部匿名类InvocationHandler的invoke(…)方法。
由30行,我们看invoke方法里面,由16-21行,一些必要的拦截;由22行,通过loadServiceMethod(method)方法获取ServiceMethod对象;由32-44行,该方法通过Map
TestApi testApi = retrofit.create(TestApi.class);
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.callAdapter.adapt(okHttpCall);
}
});
}
Call<GankBeautyResult> call = testApi.getBeauties(100, 1);
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;
}
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) {
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);
}
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
进行请求
由上,call为ExecutorCallbackCall对象,由14行,传入一个接口调用delegate.enqueue(callback)这里的delegate是OkHttpCall对象;由38-71行,我们看OkHttpCall.enqueue(final Callback callback)方法,由40-43行,是不是很熟悉?是的这里就是开始调用OkHttp3了(推荐看OkHttp3源码解析)通过request和OkHttpClient创建okhttp3.Call对象;由49行,这里就是调用Okhttp3异步请求,我们直接看onResponse回调方法是怎么处理的;由54行,通过parseResponse(okhttp3.Response)中body通过serviceMethod.toResponse(catchingBody)处理成对应的实例body;然后将该body跟okhttp3.Response一起封装成retrofit的Response对象;由59行,通过callSuccess(Response response)最终回调结果;由15-25行,ExecutorCallbackCall.enqueue方法的callback接口的onResponse回调方法收到对应的结果,这里会通过callbackExecutor切换到ui主线程执行用户传入的接口回调方法;callbackExecutor为MainThreadExecutor对象(上面有提到,你可以往上翻)该对象通过execute(runnable)继而通过方法里的 handler.post(r)切换到了主线程。(handler创建的时候是指定了主线程looper)->(你可以看看Handler消息机制以及源码分析Handle Looper MessageQueue)
call.enqueue(new Callback<GankBeautyResult>() {
@Override
public void onResponse(Call<GankBeautyResult> call, Response<GankBeautyResult> response) {
System.out.println("response content:" + response.body().beauties.size());
}
@Override
public void onFailure(Call call, Throwable t) {
}
});
@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 void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
okhttp3.Call call;
...
try {
call = rawCall = createRawCall();
} catch (Throwable t) {
failure = creationFailure = t;
}
....
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();
}
}
.....
});
}