Retrofit是一个Android网络框架,准确来说,Retrofit
是一个 Restful风格的 HTTP 网络请求框架的封装,因为它的底层网络请求是通过OkHttp
实现的,而它实际上是对网络请求接口层(请求方式、Header等信息)的封装。
Retrofit分析
Retrofit的简单使用
1、定义请求接口,配置网络请求参数
interface ApiService {
@GET("v4/rankList")
fun getCategories(): LiveData<HttpResult<CategoryDetailEntity>>
}
2、创建Retrofit实例
val retrofit = Retrofit.Builder()
.baseUrl("http://baidu.com")
.addCallAdapterFactory(LiveDataCallAdapterFactory())
.addConverterFactory(GsonConverterFactory.create())
.build()
通过Builder模式创建实例,可配置很多属性,例如CallAdapter
、ConverterFactory
等
3、创建接口的动态代理对象
val apiService = retrofit.create(ApiService::class.java)
4、使用代理对象发起网络请求,并处理回调结果
apiService.getCategories().observe(this, Observer { httpResult ->
if (true == httpResult?.isSuccessful) {
println(httpResult.data)
} else {
Toast.makeText(this@MainActivity, httpResult?.msg, Toast.LENGTH_SHORT).show()
}
})
源码分析
1、构建Retrofit实例
val retrofit = Retrofit.Builder()
.baseUrl("http://baobab.kaiyanapp.com/api/")
.addCallAdapterFactory(LiveDataCallAdapterFactory())
.addConverterFactory(GsonConverterFactory.create())
.build()
首先来看下Retrofit
的属性:
// 用于缓存对网络请求接口注解进行解析后生成的对象
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
// 网络请求的工厂(对请求进行实际处理),默认使用okhttp
final okhttp3.Call.Factory callFactory;
// 网络请求基地址
final HttpUrl baseUrl;
// 数据转换器工厂集合,把响应数据转成特定的类型
final List<Converter.Factory> converterFactories;
// 网络请求适配器工厂集合,
final List<CallAdapter.Factory> callAdapterFactories;
// 回调方法执行器,切换线程
final @Nullable
Executor callbackExecutor;
// 标志位,用于标识是否提前对业务接口中的注解进行验证转换
final boolean validateEagerly;
Retrofit
是使用建造者模式构建的,查看它的Builder
类:
public static final class Builder {
// Builder的属性和Retrofit的属性基本对应
private final Platform platform;
private @Nullable
okhttp3.Call.Factory callFactory;
private @Nullable
HttpUrl baseUrl;
private final List<Converter.Factory> converterFactories = new ArrayList<>();
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(Retrofit retrofit) {
platform = Platform.get();
callFactory = retrofit.callFactory;
baseUrl = retrofit.baseUrl;
...
callbackExecutor = retrofit.callbackExecutor;
validateEagerly = retrofit.validateEagerly;
}
可以看到,Builder中的属性基本与Retrofit的相对应,而在构造方法中传入了Platform
这个对象,这个对象指的是当前的运行平台是Android
或Java
平台等,里面提供了默认回调执行器等,我们直接看下Android
平台的关键代码:
class Platform {
...
static class Android extends Platform {
...
@Override
public Executor defaultCallbackExecutor() {
// 返回一个默认的回调方法执行器
// 作用:切换线程,子->主线程,并再主线程中执行回调方法
return new MainThreadExecutor();
}
@Override
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
// 默认请求适配器工厂
DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
return Build.VERSION.SDK_INT >= 24
? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
: singletonList(executorFactory);
}
static class MainThreadExecutor implements Executor {
// 获取主线程Handler
private final Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable r) {
handler.post(r); // 在主线程中处理网络请求返回的数据
}
}
}
}
可以看出这个回调执行器的作用就是用于线程之间的切换,在ExecutorCallbackCall
中的enqueue方法中调用了Call方法的enqueue方法,然后在回调中用MainThreadExecutor
的execute方法通过handler切换到主线程处理。
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
private final @Nullable
Executor callbackExecutor;
DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
@Override
public @Nullable
CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
...
final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
? null: callbackExecutor;
return new CallAdapter<Object, Call<?>>() {
@Override
public Type responseType() {
return responseType;
}
@Override
public Call<Object> adapt(Call<Object> call) {
return executor == null? call : new ExecutorCallbackCall<>(executor, call);
}
};
}
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);
}
});
}
});
}
...
}
}
Builder类的baseUrl方法,作用是用来配置网络请求的基地址:
public Builder baseUrl(String baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
return baseUrl(HttpUrl.get(baseUrl));
}
public Builder baseUrl(HttpUrl baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
// 切割Url成路径碎片
List<String> pathSegments = baseUrl.pathSegments();
// 检测Url是否是以“/”结尾
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}
检测Url是否是以“/”结尾,不是就抛出异常,将传入的String类型的url转成HttpUrl类型。
Builder类的addConverterFactory、addCallAdapterFactory方法:
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
callAdapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
将数据转换工厂类和网络请求适配工厂类添加到对应的集合中,供后面使用。
Builder类的build方法:
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;
// 如果没指定,则使用平台的默认的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.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// Make a defensive copy of the converters.
// 配置数据转换器工厂集合
List<Converter.Factory> converterFactories = new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
// 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);
converterFactories.addAll(platform.defaultConverterFactories());
// 构建Retrofit对象,传入上述已配置好的变量
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
将网络请求工厂、回调执行器、适配器集合等传入Retrofit的构造方法中,并返回Retrofit对象,到这里,Retrofit的属性都进行了初始化。
2、创建接口的动态代理对象
val apiService = retrofit.create(ApiService::class.java)
查看Retrofit
的create方法:
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
// 判断是否需要提前验证
if (validateEagerly) {
// 对接口中的每个方法的注解进行解析得到一个ServiceMethod的对象
// 以Method为key存入一个Map集合中
// 如果不提前验证,则会在调用方法时再对对应方法进行解析,最后将解析得到的ServiceMethod对象存入Map中
eagerlyValidateMethods(service);
}
// 创建网络请求接口的动态代理对象
return (T) Proxy.newProxyInstance(
service.getClassLoader(), // 动态生成接口的实现类
new Class<?>[]{service}, // 动态创建实例
new InvocationHandler() { // 将代理类的实现交给InvocationHandler类作为具体实现
private final Platform platform = Platform.get(); // 获取当前平台
private final Object[] emptyArgs = new Object[0];
@Override
public @Nullable
Object invoke(Object proxy, Method method,
@Nullable 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方法的invoke唤醒方法
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
通过代理模式生成一个代理对象用于访问目标对象,当使用代理对象调用方法时,调用都会集中到InvocationHandler
的invoke方法上进行处理。
流程分析:
1、检验传进来的service是否是一个接口类型
2、判断是否需要提前验证,即提前去遍历解析接口方法,得到ServiceMethod对象并存入Map中,用于缓存获取
3、调用方法交由invoke方法内部处理
3.1、判断如果当前方法所在的类是个Object,则直接通过invoke调用
3.2、判断是否是default方法,如果是,则调用platform的invokeDefaultMethod处理
3.3、调用loadServiceMethod(method)方法返回ServiceMethod对象后,再调用其invoke方法处理
接下来看下loadServiceMethod
方法:
ServiceMethod<?> loadServiceMethod(Method method) {
// 从Map缓存中取,如果有,则直接返回
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;
// 单例模式获取ServiceMethod对象
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
// 解析方法注解,返回ServiceMethod对象
result = ServiceMethod.parseAnnotations(this, method);
// 存入缓存Map中
serviceMethodCache.put(method, result);
}
}
return result;
}
判断当前方法是否已解析过(缓存中有没有),如果已解析,则直接返回,否则调用ServiceMethod
的parseAnnotations对方法进行解析,再存入Map中。
查看ServiceMethod
类:
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
// 解析方法注解并返回RequestFactory对象
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
Type returnType = method.getGenericReturnType();
// 检测方法的返回值类型
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(method,
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
abstract @Nullable
T invoke(Object[] args);
}
提供了两个方法,一个是parseAnnotations
方法:用于解析方法注解,一个是invoke
方法:用于调用对应的方法,进行网络请求。
parseAnnotations内部逻辑是:
1、对方法注解进行解析并返回一个RequestFactory对象(该对象内部封装了与请求的相关数据,例如,请求方式、请求参数等)
2、判断方法的返回类型是否合法
3、调用HttpServiceMethod的parseAnnotations并返回ServiceMethod对象
invoke方法由ServiceMethod子类
实现,常见处理是传入参数等进行网络请求,再对返回值类型进行转化,再返回转化后的数据。
现在我们先看下RequestFactory
是怎么从方法注解上解析出与请求相关的数据的:
final class RequestFactory {
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}
private final Method method; // 当前方法
private final HttpUrl baseUrl; // 基地址
final String httpMethod; // 请求方式
private final @Nullable
String relativeUrl; // 参数部分的相对路径
private final @Nullable
Headers headers; // 请求头信息
private final @Nullable
MediaType contentType; // 请求报文body的类型
private final boolean hasBody; // 是否有请求实体
private final boolean isFormEncoded; // 是否表单数据
private final boolean isMultipart;
private final ParameterHandler<?>[] parameterHandlers; // 方法参数处理器
final boolean isKotlinSuspendFunction; // 是否使用了协程
可以看到RequestFactory也是通过建造者模式构建的,查看它的Builder
类:
static final class Builder {
...
final Retrofit retrofit;
final Method method; // 方法
final Annotation[] methodAnnotations; // 方法上的注解数组
final Annotation[][] parameterAnnotationsArray; // 参数注解数组,二维数组(因为一个参数上可能也有多个注解)
final Type[] parameterTypes; // 参数类型数组
boolean gotField;
boolean gotPart;
boolean gotBody;
boolean gotPath;
boolean gotQuery;
boolean gotQueryName;
boolean gotQueryMap;
boolean gotUrl;
@Nullable
String relativeUrl;
@Nullable
Headers headers;
@Nullable
MediaType contentType;
@Nullable
Set<String> relativeUrlParamNames;
@Nullable
ParameterHandler<?>[] parameterHandlers;
boolean isKotlinSuspendFunction;
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations(); // 方法注解数组
this.parameterTypes = method.getGenericParameterTypes(); // 参数类型数组
this.parameterAnnotationsArray = method.getParameterAnnotations(); // 参数注解数组
}
在参数上和RequestFactory属性基本对应,就是通过Builder类来对RequestFactory的属性进行初始化,查看build
方法:
RequestFactory build() {
// 遍历方法上的注解数组
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation); // 解析方法上的注解
}
if (httpMethod == null) {
// 没有配置请求方式的注解
throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
// 判断使用注解方式是否正确
if (!hasBody) {
if (isMultipart) {
throw methodError(method,
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {
throw methodError(method, "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, lastParameter = parameterCount - 1; p < parameterCount; p++) {
// 为方法中的每个参数创建一个ParameterHandler<?>对象并解析每个参数使用的注解类型
// 该对象的创建过程就是对方法参数中注解进行解析
parameterHandlers[p] =
parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
}
if (relativeUrl == null && !gotUrl) {
throw methodError(method, "Missing either @%s URL or @Url parameter.", httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError(method, "Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && !gotField) {
throw methodError(method, "Form-encoded method must contain at least one @Field.");
}
if (isMultipart && !gotPart) {
throw methodError(method, "Multipart method must contain at least one @Part.");
}
return new RequestFactory(this);
}
流程分析:
1、遍历方法上的注解,调用parseMethodAnnotation方法解析注解
2、判断注解使用方式是否正确
3、对参数注解进行处理
查看parseMethodAnnotation
方法:
private void parseMethodAnnotation(Annotation annotation) {
if (annotation instanceof DELETE) { // DELETE请求
parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
} else if (annotation instanceof GET) {
parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
} else if (annotation instanceof HEAD) {
parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
} else if (annotation instanceof PATCH) {
parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
} else if (annotation instanceof POST) {
parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
} else if (annotation instanceof PUT) {
parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
} else if (annotation instanceof OPTIONS) {
parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
} else if (annotation instanceof HTTP) {
HTTP http = (HTTP) annotation;
parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
} else if (annotation instanceof retrofit2.http.Headers) { // 处理Header注解
String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
if (headersToParse.length == 0) {
throw methodError(method, "@Headers annotation is empty.");
}
// 解析Header注解上的数据
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) { // Multipart注解
if (isFormEncoded) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) { // FormUrlEncoded注解
if (isMultipart) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}
针对不同的请求方式处理,处理逻辑在parseHttpMethodAndPath方法内:
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
// 检测是否已经解析过了
if (this.httpMethod != null) {
throw methodError(method, "Only one HTTP method is allowed. Found: %s and %s.",
this.httpMethod, httpMethod);
}
this.httpMethod = httpMethod;
this.hasBody = hasBody;
if (value.isEmpty()) {
return;
}
// Get the relative URL path and existing query string, if present.
int question = value.indexOf('?'); // 获取请求链接中参数开始位置
if (question != -1 && question < value.length() - 1) { // 有参数
// Ensure the query string does not have any named parameters.
String queryParams = value.substring(question + 1);
Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
if (queryParamMatcher.find()) {
throw methodError(method, "URL query string \"%s\" must not have replace block. "
+ "For dynamic query parameters use @Query.", queryParams);
}
}
this.relativeUrl = value; // 参数部分的相对路径
this.relativeUrlParamNames = parsePathParameters(value);
}
这里实际上就是对请求方式等属性进行赋值操作,然后判断请求链接中是否有参数,有则进行解析并给对应的属性赋值。
对参数进行处理的参数处理器ParameterHandler
:
abstract class ParameterHandler<T> {
// 子类实现注解解析,将注解的值value注入到builder中
abstract void apply(RequestBuilder builder, @Nullable T value) throws IOException;
// 迭代器解析,调用apply注入value值到builder中
final ParameterHandler<Iterable<T>> iterable() {
return new ParameterHandler<Iterable<T>>() {
@Override
void apply(RequestBuilder builder, @Nullable Iterable<T> values)
throws IOException {
if (values == null) return; // Skip null values.
for (T value : values) {
ParameterHandler.this.apply(builder, value);
}
}
};
}
// 数组解析
final ParameterHandler<Object> array() {
return new ParameterHandler<Object>() {
@Override
void apply(RequestBuilder builder, @Nullable Object values) throws IOException {
if (values == null) return; // Skip null values.
for (int i = 0, size = Array.getLength(values); i < size; i++) {
//noinspection unchecked
ParameterHandler.this.apply(builder, (T) Array.get(values, i));
}
}
};
}
这个抽象类有很多子类对应@Header,@Path,@QueryMap等注解,作用就是将对应注解中的值,注入到RequestBuild中去。
到现在我们得到了RequestFactory
对象,回到ServiceMethod
的parseAnnotations中,接着调用了HttpServiceMethod
的parseAnnotations
方法,并把retrofit、requestFactory、method作为参数传入:
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;
Annotation[] annotations = method.getAnnotations(); // 获取方法上的注解数组
Type adapterType;
if (isKotlinSuspendFunction) { // 判断是否是使用了协程
...暂不分析
}
// 从Retrofit对象中获取到对应的网络请求适配器
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
Type responseType = callAdapter.responseType();
// 判断返回类型是否正确
if (responseType == okhttp3.Response.class) {
throw methodError(method, "'"
+ getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
if (responseType == Response.class) {
throw methodError(method, "Response must include generic type (e.g., Response<String>)");
}
// TODO support Unit for Kotlin?
if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
throw methodError(method, "HEAD method must use Void as response type.");
}
// 从Retrofit对象中获取到对应的数据转换器
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory; // 网络请求工厂,默认是OkHttp
if (!isKotlinSuspendFunction) {
// CallAdapted是HTTPServiceMethod的实现类
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
} else {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
continuationBodyNullable);
}
}
private final RequestFactory requestFactory;
private final okhttp3.Call.Factory callFactory;
private final Converter<ResponseBody, ResponseT> responseConverter;
整理流程:
1、根据方法注解和网络请求接口的返回值类型,从Retrofit对象中获取到对应的网络请求适配器,createCallAdapter方法
2、根据方法注解和网络请求接口的返回值类型,从Retrofit对象中获取到对应的数据转换器,createResponseConverter方法
3、获取请求工厂,默认是使用OkHttp
4、用上述几个获取的值作为参数构建出CallAdapter对象
获取网络请求适配器的createCallAdapter
方法:
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
try {
//noinspection unchecked
return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, e, "Unable to create call adapter for %s", returnType);
}
}
调用了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());
}
遍历CallAdapter工厂集合,查找返回值类型、方法注解相匹配的适配器对象,如果最终没有找到,则抛出异常。
获取数据转换器的createResponseConverter
方法:
private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(
Retrofit retrofit, Method method, Type responseType) {
Annotation[] annotations = method.getAnnotations();
try {
return retrofit.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, e, "Unable to create converter for %s", responseType);
}
}
调用了Retrofit的responseBodyConverter方法:
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
checkNotNull(type, "type == null");
checkNotNull(annotations, "annotations == null");
int start = converterFactories.indexOf(skipPast) + 1;
for (int i = start, count = converterFactories.size(); i < count; i++) {
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
if (converter != null) {
//noinspection unchecked
return (Converter<ResponseBody, T>) converter;
}
}
StringBuilder builder = new StringBuilder("Could not locate ResponseBody converter for ")
.append(type)
.append(".\n");
if (skipPast != null) {
builder.append(" Skipped:");
for (int i = 0; i < start; i++) {
builder.append("\n * ").append(converterFactories.get(i).getClass().getName());
}
builder.append('\n');
}
builder.append(" Tried:");
for (int i = start, count = converterFactories.size(); i < count; i++) {
builder.append("\n * ").append(converterFactories.get(i).getClass().getName());
}
throw new IllegalArgumentException(builder.toString());
}
遍历数据转换器工厂集合,调用转换器类查找和返回值、注解类型匹配的对象,如果最终没找到,则抛出异常。
CallAdapter
是HttpServiceMethod的实现类:
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
private final CallAdapter<ResponseT, ReturnT> callAdapter;
CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, ReturnT> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}
@Override
protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
// 调用请求适配器的adapt方法
return callAdapter.adapt(call);
}
}
查看其父类HttpServiceMethod中的invoke的实现:
HttpServiceMethod(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter) {
this.requestFactory = requestFactory;
this.callFactory = callFactory;
this.responseConverter = responseConverter;
}
@Override
final @Nullable
ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
在代理对象的InvocationHandler
中的invoke方法中我们获取到ServiceMethod
对象后调用了它的invoke方法,在invoke方法内部可以看到,首先先通过传入RequestFactory、参数、适配器等构建一个OkHttpCall
对象,再调用了adapt方法传入OkHttpCall
和参数,看回CallAdapter
中的adapt方法,所以最终调用了网络请求适配器的adapt方法。
查看DefaultCallAdapterFactory
的get方法中返回的匿名CallAdapter
对象:
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
private final @Nullable
Executor callbackExecutor; // 回调执行器
DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
@Override
public @Nullable
CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
...
return new CallAdapter<Object, Call<?>>() {
@Override
public Type responseType() {
return responseType;
}
@Override
public Call<Object> adapt(Call<Object> call) {
return executor == null ? call: new ExecutorCallbackCall<>(executor, call);
}
};
}
可以看到在adapt方法中通过传入了回调执行器和OkHttpCall
对象构建了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);
}
});
}
});
}
...
}
这里我们之前说过,主要是调用了OkHttpCall
的enqueue方法后在其回调用了Handler切换线程,那现在我们看下OKHttpCall的异步enqueue方法的实现逻辑:
final class OkHttpCall<T> implements Call<T> {
...
@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(); // 赋值得到实际进行请求的Call对象
} catch (Throwable t) {
throwIfFatal(t);
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
// 调用OkHttp的Call对象的enqueue方法
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) {
throwIfFatal(e);
callFailure(e);
return;
}
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
@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) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
});
}
}
整理下流程:
1、判断当前是否创建过OkHttp的Call对象了,如果没有,则调用createRawCall方法创建
2、判断当前请求是否取消,如果已取消,则直接调用Call对象的cancel方法后return
3、调用Call的enqueue方法,对它的回调进行处理,这里注意下parseResponse方法
createRawCall
方法:
private okhttp3.Call createRawCall() throws IOException {
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
明显,就是通过OkHttp
的newCall方法,通过传入之前创建的RequestFactory
对象来构建真正用于请求的Okhttp
的Call对象。
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();
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();
}
}
if (code == 204 || code == 205) {
rawBody.close();
return Response.success(null, rawResponse);
}
ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
try {
T body = responseConverter.convert(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;
}
}
对OkHttp
的返回的Response
对象进行错误码判断,然后调用responseConverter
数据转换器的convert对ResponseBody
进行数据转换,将得到的数据再转成Retrofit的Response对象(数据在body属性)后返回。
总结
Retrofit
通过注解的方式配置请求方式、Header等网络请求参数,简化了请求的构建,同时又提供了CallAdapter
、ConverterAdapter
适配器,方便扩展,可对返回的数据进行处理。通过使用动态代理的方式,将请求动态地处理解析成Http参数,交由OkHttp
再进行实际请求。最后,用一张图来回顾下基本的流程: