Retrofit源码分析
1、优点
A:支持同步和异步请求操作
B:支持多种数据格式(Gson、Json、XML)
C:使用注解方式配置请求参数,简单易用
D:拓展性好,支持RxJava作为convertAdapter
源码分析
构建retrofit实例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
MyApi api = retrofit.create(MyApi.class);
Response user = api.getUser().execute();
构造方法
通过构造传参方式指定参数callFactory,baseUrl,converterFactories,callAdapterFactories,callbackExecutorvalidateEagerly值
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,
@Nullable Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
Builder分析
public static final class Builder {
// 平台类型
private final Platform platform;
// okhttp请求工厂类
private @Nullable okhttp3.Call.Factory callFactory;
// baseUrl
private HttpUrl baseUrl;
// 数据转换工厂集合
private final List<Converter.Factory> converterFactories = new ArrayList<>();
// call适配器工厂集合
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
// 方法回调执行器
private @Nullable Executor callbackExecutor;
// 接口验证标志位
private boolean validateEagerly;
Builder(Platform platform) {
this.platform = platform;
}
public Builder() {
this(Platform.get());
}
查看builder构造
public Builder() {
this(Platform.get());
}
查看Platform
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
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还是java
static class Android extends Platform {
// 设定主线程回调执行器
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
// 设定默认的callAdapterFactory
if (callbackExecutor == null) throw new AssertionError();
return new ExecutorCallAdapterFactory(callbackExecutor);
}
// 通过获取主线程looper的handler发送runnable执行数据
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
baseUrl()
/**
* Set the API base URL.
*
* @see #baseUrl(HttpUrl)
*/
public Builder baseUrl(String baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
// 通过okhttp类HttpUrl中parse将baseUrl转换为HttpUrl类型
HttpUrl httpUrl = HttpUrl.parse(baseUrl);
if (httpUrl == null) {
throw new IllegalArgumentException("Illegal URL: " + baseUrl);
}
return baseUrl(httpUrl);
}
继续跟进 baseUrl(httpUrl)方法
public Builder baseUrl(HttpUrl baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
List<String> pathSegments = baseUrl.pathSegments();
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}
通过baseUrl方法首先对baseUrl进行非空判断,并截取url判断是否以/结束,最后将baseUrl赋值给全局的baseUrl
addConverterFactory(GsonConverterFactory.create())
/** Add converter factory for serialization and deserialization of objects. */
// 通过该方法向convertFactories中添加数据转换工厂
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
继续查看Converter.Factory
Factory是一个抽象类,继续查看其子类,毫无悬念,GsonConverterFactory继承该类,如果我们
想使用其他方式对数据进行解析的话,只需要继承Converter.Factory方法,重写内部的解析方法即可
abstract class Factory {
public final class GsonConverterFactory extends Converter.Factory
查看GsonConverterFactory.create()
public static GsonConverterFactory create() {
return create(new Gson());
}
// create方法
/**
* Create an instance using {@code gson} for conversion. Encoding to JSON and
* decoding from JSON (when no charset is specified by a header) will use UTF-8.
*/
@SuppressWarnings("ConstantConditions") // Guarding public API nullability.
public static GsonConverterFactory create(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
return new GsonConverterFactory(gson);
}
private GsonConverterFactory(Gson gson) {
this.gson = gson;
}
重写了请求和响应数据的解析方法
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
通过GsonRequestBodyConverter<>(gson, adapter),对数据进行转换
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
T result = adapter.read(jsonReader);
if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonIOException("JSON document was not fully consumed.");
}
return result;
} finally {
value.close();
}
}
}
builder.build()方法
/**
* Create the {@link Retrofit} instance using the configured values.
* <p>
* Note: If neither {@link #client} nor {@link #callFactory} is called a default {@link
* OkHttpClient} will be created and used.
*/
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
// 默认使用OKHttp进行网络请求
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);
}
build方法中对baseUrl、callFactory、callbackExecutor、callAdapterFactories、converterFactories进行赋值,然后通过retrofit构造方法将值进行传递,创建retrofit实例
retrofit.create(MyApi.class);
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
public <T> T create(final Class<T> service) {
// service接口判断
Utils.validateServiceInterface(service);
// 接口验证判断
if (validateEagerly) {
eagerlyValidateMethods(service);
}
// 使用动态代理方式
return (T) Proxy.newProxyInstance(service.getClassLoader(), // 动态生成接口的实现类
new Class<?>[] { service }, // 动态创建实例
new InvocationHandler() { // 将代理类的实现交给 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方法
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
// 创建okHttpCall
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
// 根据okHttpCal返回service接口类型数据
return serviceMethod.adapt(okHttpCall);
}
});
}
ServiceMethod
// 获取serviceMethod获取接口中的方法
ServiceMethod<?, ?> loadServiceMethod(Method method) {
// 先通过缓存获取method
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
// 同步缓存
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
// 构建serviceMethod实例
result = new ServiceMethod.Builder<>(this, method).build();
// private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
// 通过ConcurrentHashMap缓存method和result
serviceMethodCache.put(method, result);
}
}
return result;
}
下面跟进new ServiceMethod.Builder<>(this, method).build();
/** Adapts an invocation of an interface method into an HTTP call. */
// 适配一个接口方法用于http请求
final class ServiceMethod<R, T> {
// Builder方法
Builder(Retrofit retrofit, Method method) {
// 设置retrofit实例
this.retrofit = retrofit;
// 设置method
this.method = method;
// 设置注解
this.methodAnnotations = method.getAnnotations();
// 设置泛型参数类型
this.parameterTypes = method.getGenericParameterTypes();
// 获取参数注解数组
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
build方法
public ServiceMethod build() {
// 创建callAdapter
callAdapter = createCallAdapter();
// 获取responseType
responseType = callAdapter.responseType();
// 获取responseConverter 响应转换器
responseConverter = createResponseConverter();
// 遍历注解方法并进行解析
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
// 省略判断代码
int parameterCount = parameterAnnotationsArray.length;
// 根据参数数量创建指定长队的ParameterHandler数组
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);
}
// 解析注解参数置于parameterAnnotations数组中
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
//解析注解参数数据
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
// 调用ServiceMethod构造方法创建serviceHandler实例
return new ServiceMethod<>(this);
}
解析参数ParameterHandler<?> parseParameter
private ParameterHandler<?> parseParameter(
int p, Type parameterType, Annotation[] annotations) {
ParameterHandler<?> result = null;
for (Annotation annotation : annotations) {
ParameterHandler<?> annotationAction = parseParameterAnnotation(
p, parameterType, annotations, annotation);
if (annotationAction == null) {
continue;
}
if (result != null) {
throw parameterError(p, "Multiple Retrofit annotations found, only one allowed.");
}
result = annotationAction;
}
if (result == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
return result;
}
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
private final ServiceMethod<T, ?> serviceMethod;
private final @Nullable Object[] args;
// 通过构造设置serviceMethod和args
OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
return serviceMethod.adapt(okHttpCall);
T adapt(Call<R> call) {
return callAdapter.adapt(call);
}
默认返回call类型
public interface CallAdapter<R, T> {
CallAdapter为接口类型如果我们想要自定义网络请求适配器,可以实现CallAdapter
类似final class RxJava2CallAdapter implements CallAdapter
enqueue异步请求方法
查看okHttpCall中enqueue方法
@Override public void enqueue(final Callback<T> callback) {
// 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赋值
call = rawCall = createRawCall();
} catch (Throwable t) {
throwIfFatal(t);
failure = creationFailure = t;
}
}
}
// 请求失败直接回调onFailed
if (failure != null) {
callback.onFailure(this, failure);
return;
}
// 请求取消回调cancel
if (canceled) {
call.cancel();
}
// 异步执行请求
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
// 解析原始请求rawResponse
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();
}
}
});
}
里面有两个方法需要查看下
parseResponse(rawResponse)
callFailure(e);
继续跟进查看如下
parseResponse
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
// Remove the body's source (the only stateful object) so we can pass the response along.
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
int code = rawResponse.code();
// 回调error
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
// 回调success
if (code == 204 || code == 205) {
rawBody.close();
return Response.success(null, rawResponse);
}
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}
parseResponse通过rawResponse获取code码,根据code码返回response类型数据
callFailure(e);
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
可见该方法直接简单回调了下onFailure(OkHttpCall.this, e)方法,将异常通过回调方法进行传递
execute()方法
@Override public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
// 针对异常抛出
if (creationFailure != null) {
if (creationFailure instanceof IOException) {
throw (IOException) creationFailure;
} else if (creationFailure instanceof RuntimeException) {
throw (RuntimeException) creationFailure;
} else {
throw (Error) creationFailure;
}
}
// 单例方式创建call实例
call = rawCall;
if (call == null) {
try {
// 创建call实例
call = rawCall = createRawCall();
} catch (IOException | RuntimeException | Error e) {
throwIfFatal(e); // Do not assign a fatal error to creationFailure.
creationFailure = e;
throw e;
}
}
}
if (canceled) {
call.cancel();
}
// 解析响应数据
return parseResponse(call.execute());
}
// 通过serviceMethod
private okhttp3.Call createRawCall() throws IOException {
// 通过toCall方法获取call实例
okhttp3.Call call = serviceMethod.toCall(args);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
serviceMethod.toCall(args)方法源码查看
// 通过方法参数构建HTTP请求
/** Builds an HTTP request from method arguments. */
okhttp3.Call toCall(@Nullable Object... args) throws IOException {
// 构建RequestBuilder实例
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
contentType, hasBody, isFormEncoded, isMultipart);
@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args != null ? args.length : 0;
if (argumentCount != handlers.length) {
throw new IllegalArgumentException("Argument count (" + argumentCount
+ ") doesn't match expected count (" + handlers.length + ")");
}
// 添加请求参数
for (int p = 0; p < argumentCount; p++) {
handlers[p].apply(requestBuilder, args[p]);
}
// 通过callFactory创建新的请求,实际上是调用okHttpClient进行请求
return callFactory.newCall(requestBuilder.build());
}