Retrofit是一个Android网络框架,准确来说,Retrofit是一个 Restful风格的 HTTP 网络请求框架的封装,因为它的底层网络请求是通过OkHttp实现的,而它实际上是对网络请求接口层(请求方式、Header等信息)的封装。

Retrofit分析

  • Retrofit的简单使用
  • 源码分析
    • 1、构建Retrofit实例
    • 2、创建接口的动态代理对象
  • 总结

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模式创建实例,可配置很多属性,例如CallAdapterConverterFactory

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 @Nullableokhttp3.Call.Factory callFactory;private @NullableHttpUrl baseUrl;private final List<Converter.Factory> converterFactories = new ArrayList<>();private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();private @NullableExecutor 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这个对象,这个对象指的是当前的运行平台是AndroidJava平台等,里面提供了默认回调执行器等,我们直接看下Android平台的关键代码:

class Platform {...static class Android extends Platform {...@Overridepublic Executor defaultCallbackExecutor() {// 返回一个默认的回调方法执行器// 作用:切换线程,子->主线程,并再主线程中执行回调方法return new MainThreadExecutor();}@OverrideList<? 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 {// 获取主线程Handlerprivate final Handler handler = new Handler(Looper.getMainLooper());@Overridepublic void execute(Runnable r) {handler.post(r); // 在主线程中处理网络请求返回的数据}}}
}

可以看出这个回调执行器的作用就是用于线程之间的切换,在ExecutorCallbackCall中的enqueue方法中调用了Call方法的enqueue方法,然后在回调中用MainThreadExecutor的execute方法通过handler切换到主线程处理。

final class DefaultCallAdapterFactory extends CallAdapter.Factory {private final @NullableExecutor callbackExecutor;DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {this.callbackExecutor = callbackExecutor;}@Overridepublic @NullableCallAdapter<?, ?> 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<?>>() {@Overridepublic Type responseType() {return responseType;}@Overridepublic 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;}@Overridepublic void enqueue(final Callback<T> callback) {checkNotNull(callback, "callback == null");delegate.enqueue(new Callback<T>() {@Overridepublic void onResponse(Call<T> call, final Response<T> response) {callbackExecutor.execute(new Runnable() {@Overridepublic 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);}}});}@Overridepublic void onFailure(Call<T> call, final Throwable t) {callbackExecutor.execute(new Runnable() {@Overridepublic 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;// 如果没指定,默认使用OkHttpif (callFactory == null) {callFactory = new OkHttpClient();}// 配置回调执行器Executor callbackExecutor = this.callbackExecutor;// 如果没指定,则使用平台的默认的callBackExecutorif (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];@Overridepublic @NullableObject 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 @NullableT 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 @NullableString relativeUrl; // 参数部分的相对路径private final @NullableHeaders headers; // 请求头信息private final @NullableMediaType 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;@NullableString relativeUrl;@NullableHeaders headers;@NullableMediaType contentType;@NullableSet<String> relativeUrlParamNames;@NullableParameterHandler<?>[] 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>>() {@Overridevoid 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>() {@Overridevoid 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 uncheckedParameterHandler.this.apply(builder, (T) Array.get(values, i));}}};}

这个抽象类有很多子类对应@Header,@Path,@QueryMap等注解,作用就是将对应注解中的值,注入到RequestBuild中去。

到现在我们得到了RequestFactory对象,回到ServiceMethod的parseAnnotations中,接着调用了HttpServiceMethodparseAnnotations方法,并把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; // 网络请求工厂,默认是OkHttpif (!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 uncheckedreturn (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 uncheckedreturn (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;}@Overrideprotected 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 @NullableExecutor callbackExecutor; // 回调执行器DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {this.callbackExecutor = callbackExecutor;}@Overridepublic @NullableCallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {...return new CallAdapter<Object, Call<?>>() {@Overridepublic Type responseType() {return responseType;}@Overridepublic 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;}@Overridepublic void enqueue(final Callback<T> callback) {checkNotNull(callback, "callback == null");// 执行请求delegate.enqueue(new Callback<T>() {@Overridepublic void onResponse(Call<T> call, final Response<T> response) {callbackExecutor.execute(new Runnable() { // 回调执行器切换线程@Overridepublic 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);}}});}@Overridepublic void onFailure(Call<T> call, final Throwable t) {callbackExecutor.execute(new Runnable() {@Overridepublic 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等网络请求参数,简化了请求的构建,同时又提供了CallAdapterConverterAdapter适配器,方便扩展,可对返回的数据进行处理。通过使用动态代理的方式,将请求动态地处理解析成Http参数,交由OkHttp再进行实际请求。最后,用一张图来回顾下基本的流程:

Retrofit2源码分析相关推荐

  1. Retrofit2源码分析(一)

    本文将顺着构建请求对象→构建请求接口→发起同步/异步请求的流程,分析retrofit2是如何实现的. 组成部分 Retrofit2源码主要分为以下几个部分: retrofit retrofit-ada ...

  2. Retrofit2源码解读

    综述 Retrofit2的用法在Retrofit2.0使用详解这篇文章中已经详细介绍过了.那么在这就来看一下Retrofit2它是如何实现的.Retrofit2中它的内部网络请求是依赖于OKHttp, ...

  3. Retrofit2.0 源码分析

    前言 注解式的框架非常火,注解以其轻量,简洁等特性被人们所喜爱者,关键是它解藕.网络请求的框架非常多,比较受欢迎的当属retrofit和okHttp了.连retrofit都是基于okHttp之上开发的 ...

  4. Retrofit2源码解析——网络调用流程(下)

    Retrofit2源码解析系列 Retrofit2源码解析(一) Retrofit2源码解析--网络调用流程(上) 本文基于Retrofit2的2.4.0版本 implementation 'com. ...

  5. Android Retrofit 2.0(三)从源码分析原理

    Retrofit·特点 性能最好,处理最快 使用REST API时非常方便: 传输层默认就使用OkHttp: 支持NIO: 拥有出色的API文档和社区支持 速度上比volley更快: 如果你的应用程序 ...

  6. 【Android】Retrofit基础源码分析

    文章目录 流程图 基本使用 1. 创建服务端ApiInterface 2.配置BaseUrl生成Retrofit对象 3.生成服务端ApiInterface对象 4.调用服务端ApiInterface ...

  7. Retrofit2源码解析

    一.前言: Retrofit: 一个 Restful 设计风格的 HTTP 网络请求框架的封装.基于 OkHttp 严格地说,Retrofit2并不是一个网络请求交易框架,它只是对网络请求框架的封装. ...

  8. Android框架源码分析——从设计模式角度看 Retrofit 核心源码

    Android框架源码分析--从设计模式角度看 Retrofit 核心源码 Retrofit中用到了许多常见的设计模式:代理模式.外观模式.构建者模式等.我们将从这三种设计模式入手,分析 Retrof ...

  9. Retrofit2 源码解析

    Retrofit是什么 简单的说它是一个基于OkHttp的RESTFUL Api请求工具,从功能上来说和Google的Volley功能上很相似,但是使用上很不相似. Retrofit怎么用 比如你要请 ...

最新文章

  1. JAVA面试题系列:如何解决Redis的并发竞争问题
  2. 02-vue过滤器和键盘修饰符
  3. 模型评估——ROC、KS
  4. nfvo通过调用哪个接口实现对vnf生命周期的管理_Spring-Bean生命周期
  5. 前端学习(1327):node全局对象global
  6. 《C#本质论》读书笔记(十二)构造器 @ Lennon
  7. dw新建php文件自动生成html,dw如何新建css规则
  8. 微服务升级_SpringCloud Alibaba工作笔记0023---Nacos之Namespace空间方案
  9. 本地时间转utc时间_有关机器时间、UTC时间、本地时间的总结
  10. 基于OpenCV与MFC的人脸识别
  11. 字符(串)转换ASCII码
  12. LD_PRELOAD实现API劫持
  13. 不学网php线下培训视频教程
  14. linux 刷新网络配置,3 Linux 网络配置
  15. 机器学习十大算法实现代码汇总(python)----线性回归、逻辑回归、决策树、支持向量机、朴素贝叶斯、K邻近算法、K-均值算法、随机森林、降低维度算法、梯度增强算法
  16. Modern Standby 调试的准备
  17. 企业纯内网二进制完美部署Docker(20.10.7版本)
  18. Intel CPU型号解读以及如何粗略判断Intel CPU的性能(i3、i5、i7以及CPU的代数)
  19. 微信、QQ、支付宝运动步数自定义小工具
  20. CES 2023:华硕轻薄本创新形态+硬核配置引领新创作时代

热门文章

  1. HTML中拖动消失的球代码,js拖拽360桌面悬浮球代码
  2. 干票大的,230万篇文章随你下载!
  3. My命名空间——VB.NET
  4. Codeforces——C. Anu Has a Function
  5. 图像仿射变换原理3:仿射变换类型及变换矩阵详解
  6. 2021年2月CFA考试费用是多少?
  7. KONG网关 — 介绍安装
  8. (转)通用权限管理设计 之 数据权限
  9. 人工智能论文术语集27
  10. 推荐一个基于SpringBoot的在线课程管理系统开源项目,超级棒!