Android之网络请求11————Retrofit的源码分析
Android之网络请求11————Retrofit的源码分析
文章目录
- Android之网络请求11————Retrofit的源码分析
- 一.前言
- 二.Retrofit的大致流程分析
- 三.Retrofit的简单使用
- 四.源码分析--创建Retrofit实例
- 1.使用步骤
- 2.Retrofit
- 3.Builder()
- 4.baseUrl()
- 5.addConverterFactory()
- 6.build()
- 7.总结
- 五.源码分析--创建网络请求接口的实例
- 1.使用步骤
- 2.loadServiceMethod
- 3. new OkHttpCall
- 4.serviceMethod.adapt(okHttpCall);
- 六.源码分析--生成Call对象
- 1.使用步骤
- 2.讲解
- 七.源码分析--执行网络请求
- 1.同步请求
- 2.异步请求
- 八.Retrofit源码总结+流程图
- 1.总结
- 2.源码分析图
- 3.流程图
- 九.参考资料
- 十.文章索引
一.前言
前两篇文章主要分析了Retrofit的应用,这一篇主要分析的源码。在分析源码的时候,发现了一篇很好的博客,以及一个讲解视频,这里分享给大家
Retrofit分析-漂亮的解耦套路(视频版)
Android:手把手带你 深入读懂 Retrofit 2.0 源码
二.Retrofit的大致流程分析
一般网络请求的过程:

Retrofit和上面本质上是差不多的,只不过Retrofit通过使用大量的设计模式进行功能模块的解耦,使得上面的过程更加简单。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-42cPquxD-1616403739453)(
]
)
具体过程解释如下:
- 通过解析网络请求接口的注解 配置网络请求参数
- 通过动态代理生成网络请求对象
- 通过网络请求适配器将网络请求对象进行平台适配
- 通过网络请求执行器发送网络请求
- 通过数据转换器解析服务器返回的数据
- 通过回调执行器切换线程(子–>主线程)
- 用户在主线程处理返回结果
三.Retrofit的简单使用
关于Retrofir的使用可以看我之前的博客
Android之网络请求8————Retrofit的简单使用
四.源码分析–创建Retrofit实例
1.使用步骤
//a.创建Retrofit对象Retrofit retrofit = new Retrofit.Builder()//指定baseurl.baseUrl("https://api.douban.com/v2/movie/")//设置内容格式,这种对应的数据返回值是String类型.addConverterFactory(GsonConverterFactory.create())//创建.build();
我们在这里简单的创建了一个Retrofit对象,通过链式调用,总共进行了4项。我们一个个来看。
2.Retrofit
先来看Retrofit的构造函数和它所持有的参数
public final class Retrofit {//网络请求配置对象的集合。//ServiceMethod解析注解private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();//网络请求器的生产工厂final okhttp3.Call.Factory callFactory;//网络请求的URL对象final HttpUrl baseUrl;//数据转换器的工厂集合final List<Converter.Factory> converterFactories;//网络请求适配器的请求工厂集合final List<CallAdapter.Factory> callAdapterFactories;//回调方法的执行器final @Nullable Executor callbackExecutor;// 标志位 // 作用:是否提前对业务接口中的注解进行验证转换的标志位final boolean validateEagerly;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;}
}
3.Builder()
来继续看Builder方法
public static final class Builder {private final Platform platform;private @Nullable okhttp3.Call.Factory callFactory;private 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方法中变量基本和Retrofit中的保持一致,所以Retrofit类的成员变量基本上是通过Builder类进行配置
被调用的Builder的构造函数
Builder(Platform platform) {this.platform = platform;}public Builder() {this(Platform.get());}
这里可以看出Builder里面设置了默认平台。
查看Platform.get()
class 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) {//Android平台return new Android(); }} catch (ClassNotFoundException ignored) {}try {//Java8Class.forName("java.util.Optional");return new Java8();} catch (ClassNotFoundException ignored) {}return new Platform();}}
继续来看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 {//获取与主线程绑定的Handlerprivate final Handler handler = new Handler(Looper.getMainLooper());@Override public void execute(Runnable r) {// 在UI线程进行对网络请求返回数据处理等操作。handler.post(r);}}}
小结:Builder设置了默认的
- 平台类对象:Android
- 网络请求适配器工厂:CallAdapterFactory
- 回调执行器:callbackExecutor
4.baseUrl()
public Builder baseUrl(String baseUrl) {//判空处理checkNotNull(baseUrl, "baseUrl == null");//下面分析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");//把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;}
小结:
- baseUrl()用于配置Retrofit类的网络请求url地址
5.addConverterFactory()
继续分析addConverterFactory(GsonConverterFactory.create())语句。首先来看GsonConverterFactory.create()
a.GsonConverterFactory.create()
public final class GsonConverterFactory extends Converter.Factory {/*** Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and* decoding from JSON (when no charset is specified by a header) will use UTF-8.*/public static GsonConverterFactory create() {return create(new Gson());}/*** 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 final Gson gson;private GsonConverterFactory(Gson gson) {this.gson = gson;}}
GsonConverterFactory.creat()是创建了一个含有Gson对象实例的GsonConverterFactory,并返回给addConverterFactory(),继续来看了addConverterFactory()方法
b.addConverterFactory()
/** Add converter factory for serialization and deserialization of objects. */// 将上面创建的GsonConverterFactory放入到 converterFactories数组
// 在第二步放入一个内置的数据转换器工厂BuiltInConverters()后又放入了一个GsonConverterFactorypublic Builder addConverterFactory(Converter.Factory factory) {converterFactories.add(checkNotNull(factory, "factory == null"));return this;}
总结:这一步中将含有Gson对象实例的GsonConverterFactory并放入到数据转换器工厂converterFactories里
6.build()
public Retrofit build() {if (baseUrl == null) {throw new IllegalStateException("Base URL required.");}//配置call//默认使用OkHttp的Callokhttp3.Call.Factory callFactory = this.callFactory;if (callFactory == null) {callFactory = new OkHttpClient();}//配置回调方法执行器//如果没有指定,则是使用默认的callbackExecutor//即Android默认的callbackExecutorExecutor 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);// 向该集合中添加了步骤2中创建的CallAdapter.Factory请求适配器(添加在集合器末尾)callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));// Make a defensive copy of the converters.//配置数据转换器工厂:converterFactory 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);// 最终返回一个Retrofit的对象,并传入上述已经配置好的成员变量return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);}
小结:最后一步中,通过前面步骤设置的变量,将Retrofit类的所有成员变量都配置完毕。
7.总结
在构造Retrofit时,通过建造者模式Builder类,具体创建细节就是配置了:
- 平台类型对象(Platform - Android)
- 网络请求的url地址(baseUrl)
- 网络请求工厂(callFactory)
- 网络请求适配器工厂的集合(adapterFactories)
本质是配置了网络请求适配器工厂- 默认是ExecutorCallAdapterFactory
- 数据转换器工厂的集合(converterFactories)
- 回调方法执行器(callbackExecutor)
五.源码分析–创建网络请求接口的实例
1.使用步骤
<-- 步骤1:定义接收网络数据的类 -->
<-- JavaBean.java -->
public class JavaBean {.. // 这里就不介绍了}<-- 步骤2:定义网络请求的接口类 -->
public interface RetrofitInterface {@GET("in_theaters")Call<Theaters> theaters(@QueryMap Map<String ,Object>map);
}<-- 步骤3:在MainActivity创建接口类实例 -->RetrofitInterface retrofitInterface = retrofit.create(RetrofitInterface.class);
直接看retrofit.create的源码
public <T> T create(final Class<T> service) {Utils.validateServiceInterface(service);if (validateEagerly) {//判断是否需要提前验证eagerlyValidateMethods(service);// 具体方法作用: // 1. 给接口中每个方法的注解进行解析并得到一个ServiceMethod对象 // 2. 以Method为键将该对象存入LinkedHashMap集合中 // 特别注意:如果不是提前验证则进行动态解析对应方法(下面会详细说明),得到一个ServiceMethod对象,最后存入到LinkedHashMap集合中,类似延迟加载(默认)}//创建了网络请求接口的动态代理//该动态地理为了拿到网络请求接口实例上的所有注解return (T) Proxy.newProxyInstance(service.getClassLoader(), //动态实现接口的实现类new Class<?>[] { service },//动态创建实例new InvocationHandler() {//将代理类的实现交给 InvocationHandler类作为具体的实现private final Platform platform = Platform.get();// 在 InvocationHandler类的invoke()实现中,除了执行真正的逻辑(如再次转发给真正的实现类对象),还可以进行一些有用的操作// 如统计执行时间、进行初始化和清理、对接口调用进行检查等。@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对象//下面详细分析小标题1ServiceMethod<Object, Object> serviceMethod =(ServiceMethod<Object, Object>) loadServiceMethod(method);//作用:根据配置好的serviceMethod对象创建okHttpCall对象 //下面分析OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);//作用:调用OkHttp,并根据okHttpCall返回rejava的Observe对象或者返回Callreturn serviceMethod.adapt(okHttpCall);}});}//第五行代码代码的内容// 将传入的ServiceMethod对象加入LinkedHashMap集合 // 使用LinkedHashMap集合的好处:lruEntries.values().iterator().next()获取到的是集合最不经常用到的元素,//提供了一种Lru算法的实现private void eagerlyValidateMethods(Class<?> service) {Platform platform = Platform.get();for (Method method : service.getDeclaredMethods()) {if (!platform.isDefaultMethod(method)) {loadServiceMethod(method);}}}
2.loadServiceMethod
// 一个 ServiceMethod 对象对应于网络请求接口里的一个方法
// loadServiceMethod(method)负责加载 ServiceMethod:ServiceMethod<?, ?> loadServiceMethod(Method method) {ServiceMethod<?, ?> result = serviceMethodCache.get(method);if (result != null) return result;synchronized (serviceMethodCache) {// ServiceMethod类对象采用了单例模式进行创建// 即创建ServiceMethod对象前,先看serviceMethodCache有没有缓存之前创建过的网络请求实例// 若没缓存,则通过建造者模式创建 serviceMethod 对象result = serviceMethodCache.get(method);if (result == null) {//下面详细分析ServiceMethodresult = new ServiceMethod.Builder<>(this, method).build();serviceMethodCache.put(method, result);}}return result;}
我们继续来看ServiceMethod的构造过程
a.ServiceMethod类 构造函数
final class ServiceMethod<R, T> {// Upper and lower characters, digits, underscores, and hyphens, starting with a character.static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*";static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);private final okhttp3.Call.Factory callFactory; //网络请求工厂private final CallAdapter<R, T> callAdapter;//网络请求适配器private final HttpUrl baseUrlprivate final Converter<ResponseBody, R> responseConverter;//内容转换器private final String httpMethod;//Http的请求方法private final String relativeUrl;//网络请求的相对地址private final Headers headers;//http的请求头private final MediaType contentType;// 网络请求的http报文body的类型//这是三个变量是表明请求体的类型private final boolean hasBody; private final boolean isFormEncoded;private final boolean isMultipart;// 方法参数处理器// 作用:负责解析 API 定义时每个方法的参数,并在构造 HTTP 请求时设置参数;// 下面会详细说明private final ParameterHandler<?>[] parameterHandlers;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;}}
b.Builder
Builder(Retrofit retrofit, Method method) {this.retrofit = retrofit;this.method = method;this.methodAnnotations = method.getAnnotations();this.parameterTypes = method.getGenericParameterTypes();this.parameterAnnotationsArray = method.getParameterAnnotations();}
c.build()
public ServiceMethod build() {// 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取对应的网络请求适配器 -->关注点1callAdapter = createCallAdapter();// 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取该网络适配器返回的数据类型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?");}// 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取对应的数据转换器 -->关注点3 // 构造 HTTP 请求时,我们传递的参数都是String// Retrofit 类提供 converter把传递的参数都转化为 String// 其余类型的参数都利用 Converter.Factory 的stringConverter 进行转换 // @Body 和 @Part 类型的参数利用Converter.Factory 提供的 requestBodyConverter 进行转换 // 这三种 converter 都是通过“询问”工厂列表进行提供,而工厂列表我们可以在构造 Retrofit 对象时进行添加。responseConverter = createResponseConverter();// 解析网络请求接口中方法的注解// 主要是解析获取Http请求的方法// 注解包括:DELETE、GET、POST、HEAD、PATCH、PUT、OPTIONS、HTTP、retrofit2.http.Headers、Multipart、FormUrlEncoded // 处理主要是调用方法 parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) ServiceMethod中的httpMethod、hasBody、relativeUrl、relativeUrlParamNames域进行赋值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);}//为方法中的每个参数创建一个ParameterHandler>对象并解析每个参数使用的注解类型//该对象的创建过程就是对方法参数中注解进行解析//这里的注解包括:Body、PartMap、Part、FieldMap、Field、Header、QueryMap、Query、Path、Url 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);}
关注点1:createCallAdapter()
private CallAdapter<T, R> createCallAdapter() {//获取网络请求接口里方法的返回值类型Type returnType = method.getGenericReturnType();if (Utils.hasUnresolvableType(returnType)) {throw methodError("Method return type must not include a type variable or wildcard: %s", returnType);}if (returnType == void.class) {throw methodError("Service methods cannot return void.");}//获取网络请求接口接口里的注解Annotation[] annotations = method.getAnnotations();try {//noinspection unchecked//根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取对应的网络请求//关注点2return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);} catch (RuntimeException e) { // Wide exception range because factories are user code.throw methodError(e, "Unable to create call adapter for %s", returnType);}}
关注点2: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");// 创建 CallAdapter 如下// 遍历 CallAdapter.Factory 集合寻找合适的工厂(该工厂集合在第一步构造 Retrofit 对象时进行添加(第一步时已经说明))// 如果最终没有工厂提供需要的 CallAdapter,将抛出异常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());}
关注点3:createResponseConverter()
private Converter<ResponseBody, T> createResponseConverter() {Annotation[] annotations = method.getAnnotations();try {// responseConverter 还是由 Retrofit 类提供 -->关注点4return retrofit.responseBodyConverter(responseType, annotations);} catch (RuntimeException e) { // Wide exception range because factories are user code.throw methodError(e, "Unable to create converter for %s", responseType);}}
关注点4: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 过程:(和获取 callAdapter 基本一致)Converter<ResponseBody, ?> converter =converterFactories.get(i).responseBodyConverter(type, annotations, this);if (converter != null) {//noinspection uncheckedreturn (Converter<ResponseBody, T>) converter;// 遍历 Converter.Factory 集合并寻找合适的工厂(该工厂集合在构造 Retrofit 对象时进行添加(第一步时已经说明))// 由于构造Retroifit采用的是Gson解析方式,所以取出的是GsonResponseBodyConverter // Retrofit - Converters 还提供了 JSON,XML,ProtoBuf 等类型数据的转换功能。 // 继续看responseBodyConverter() -->关注点5}}//抛出异常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());}
- 关注点5:responseBodyConverter()**
查看 GsonConverterFactory的实现类
@Overridepublic Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,Retrofit retrofit) {TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));return new GsonResponseBodyConverter<>(gson, adapter);}
做数据转换时调用 Gson 的 API 即可。
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();}}
}
3. new OkHttpCall
回到Retrofit的 create函数中,查看 OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);的内容
final class OkHttpCall<T> implements Call<T> {private final ServiceMethod<T, ?> serviceMethod; //含有所有请求参数信息的对象private final @Nullable Object[] args;//网络请求接口的参数private volatile boolean canceled;@GuardedBy("this")private @Nullable okhttp3.Call rawCall;@GuardedBy("this") // Either a RuntimeException, non-fatal Error, or IOException.private @Nullable Throwable creationFailure;//几个状态标记位@GuardedBy("this")private boolean executed;OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {this.serviceMethod = serviceMethod;this.args = args;}
}
4.serviceMethod.adapt(okHttpCall);
回到Retrofit的 create函数中,return serviceMethod.adapt(okHttpCall);中的内容
将第二步创建的OkHttpCall对象传给第一步创建的serviceMethod对象中对应的网络请求适配器工厂的adapt()
adapt()详解
T adapt(Call<R> call) {return callAdapter.adapt(call);}
在这里调用了callAdapter的.adapt, Android默认的是Call<>;若设置了RxJavaCallAdapterFactory,返回的则是Observable<>
android默认:
@Override public Call<Object> adapt(Call<Object> call) {return new ExecutorCallbackCall<>(callbackExecutor, call);}ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {//传入上面定义的回调方法执行器this.callbackExecutor = callbackExecutor;//把上面创建并配置好参数的OkhttpCall对象交给静态代理delegatethis.delegate = delegate;}
Rxjava
@Override public <R> Object adapt(Call<R> call) {Observable<Response<R>> responseObservable = new CallObservable<>(call);Observable<?> observable;if (isResult) {observable = new ResultObservable<>(responseObservable);} else if (isBody) {observable = new BodyObservable<>(responseObservable);} else {observable = responseObservable;}if (scheduler != null) {observable = observable.subscribeOn(scheduler);}if (isFlowable) {return observable.toFlowable(BackpressureStrategy.LATEST);}if (isSingle) {return observable.singleOrError();}if (isMaybe) {return observable.singleElement();}if (isCompletable) {return observable.ignoreElements();}return observable;}
六.源码分析–生成Call对象
1.使用步骤
Call<JavaBean> call = NetService.getCall();
2.讲解
- NetService对象实际上是动态代理对象Proxy.newProxyInstance()(步骤3中已说明),并不是真正的网络请求接口创建的对象
- 当NetService对象调用getCall()时会被动态代理对象Proxy.newProxyInstance()拦截,然后调用自身的InvocationHandler # invoke()
- invoke(Object proxy, Method method, Object… args)会传入3个参数:Object proxy:(代理对象),Method method(调用的getCall()),Object… args(方法的参数,即getCall()中的)
- 接下来利用Java反射获取到getCall()的注解信息,配合args参数创建ServiceMethod对象。
- 最终通过getCall获得的是invoke的返回值。
七.源码分析–执行网络请求
Retrofit默认使用OkHttp,即OkHttpCall类(实现了 retrofit2.Call接口)
OkHttpCall提供了两种网络请求方式:
- 同步请求:OkHttpCall.execute()
- 异步请求:OkHttpCall.enqueue()
对于OkHttpCall的enqueue()、execute()的源码,有兴趣可以看看我前面的博客关于OKHttp的源码的文章
1.同步请求
Response<JavaBean> response = call.execute();
此时call是ExecutorCallbackCall类型,来看其execute()实现
@Override public Response<T> execute() throws IOException {return delegate.execute();}
delegete是OkHttpCall类型的,来看其实现
@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 = rawCall;if (call == null) {try {// 步骤1:创建一个OkHttp的Request对象请求 -->关注1call = 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();}// 步骤2:调用OkHttpCall的execute()发送网络请求(同步)// 步骤3:解析网络请求返回的数据parseResponse() -->关注2return parseResponse(call.execute());}
关注1
private okhttp3.Call createRawCall() throws IOException {// 根据serviceMethod和request对象创建 一个okhttp3.Requestokhttp3.Call call = serviceMethod.toCall(args);if (call == null) {throw new NullPointerException("Call.Factory returned null.");}return call;}
关注2
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);}ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);try {/// 等Http请求返回后 & 通过状态码检查后,将response body传入ServiceMethod中,//ServiceMethod通过调用Converter接口(之前设置的GsonConverterFactory)//将response body转成一个Java对象,即解析返回的数据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;}}
注意:
- ServiceMethod几乎保存了一个网络请求所需要的数据
- 发送网络请求时,OkHttpCall需要从ServiceMethod中获得一个Request对象
- 解析数据时,还需要通过ServiceMethod使用Converter(数据转换器)转换成Java对象进行数据解析
为了提高效率,Retrofit还会对解析过的请求ServiceMethod进行缓存,存放在Map
serviceMethodCache = new LinkedHashMap<>();对象中,即第二步提到的单例模式
2.异步请求
使用步骤
call.enqueue(new Callback<Theaters>() {//请求成功时回调@Overridepublic void onResponse(Call<Theaters> call, Response<Theaters> response) {response.body().show();}//请求失败时回调@Overridepublic void onFailure(Call<Theaters> call, Throwable throwable) {Log.e("retrofit", "onFailure: " + throwable);}});
同上面一样,此次的call是ExecutorCallbackCall类型,来看其execute()实现
@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() {// 最后Okhttp的异步请求结果返回到callbackExecutor// callbackExecutor.execute()通过Handler异步回调将结果传回到主线程进行处理//(如显示在Activity等等),即进行了线程切换@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);}});}});}
此处的delegate是OkHttpCall类型,来继续看enqueue的实现
@Override public void enqueue(final Callback<T> callback) {checkNotNull(callback, "callback == null");okhttp3.Call call;Throwable failure;// 步骤1:创建OkHttp的Request对象,再封装成OkHttp.call// delegate代理在网络请求前的动作:创建OkHttp的Request对象,再封装成OkHttp.callsynchronized (this) {if (executed) throw new IllegalStateException("Already executed.");executed = true;call = rawCall;failure = creationFailure;if (call == null && failure == null) {try {// 创建OkHttp的Request对象,再封装成OkHttp.call// 方法同发送同步请call = rawCall = createRawCall();} catch (Throwable t) {throwIfFatal(t);failure = creationFailure = t;}}}if (failure != null) {callback.onFailure(this, failure);return;}if (canceled) {call.cancel();}// 步骤2:发送网络请求// delegate是OkHttpcall的静态代理// delegate静态代理最终还是调用Okhttp.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) {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();}}});}
那么enqueue是在什么时候继续线程切换的?
线程切换是通过一开始创建Retrofit对象时Platform在检测到运行环境是Android时进行创建的,在前面也进行了分析
static class Android extends Platform {@Override public Executor defaultCallbackExecutor() {// 返回一个默认的回调方法执行器// 该执行器负责在主线程(UI线程)中执行回调方法return new MainThreadExecutor();}// 创建默认的回调执行器工厂// 如果不将RxJava和Retrofit一起使用,一般都是使用该默认的CallAdapter.Factory@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {if (callbackExecutor == null) throw new AssertionError();return new ExecutorCallAdapterFactory(callbackExecutor);}// 获取主线程Handlerstatic class MainThreadExecutor implements Executor {private final Handler handler = new Handler(Looper.getMainLooper());@Override public void execute(Runnable r) {// Retrofit获取了主线程的handler// 然后在UI线程执行网络请求回调后的数据显示等操作。handler.post(r);}}}
// 切换线程的流程:// 1. 回调ExecutorCallAdapterFactory生成了一个ExecutorCallbackCall对象// 2. 通过调用ExecutorCallbackCall.enqueue(CallBack)从而调用MainThreadExecutor的execute()通过handler切换到主线程处理返回结果(如显示在Activity等等)
八.Retrofit源码总结+流程图
1.总结
Retrofit本质是一个一个 RESTful 的HTTP 网络请求框架的封装,即通过 大量的设计模式 封装了 OkHttp ,使得简洁易用。具体过程如下:
- Retrofit将Http请求抽象成java接口
- 在接口里用注解描述和配置网络请求参数
- 用动态代理的方式,动态将网络请求的注解解析成HTTP请求
- 最后执行HTTP请求
2.源码分析图

3.流程图

九.参考资料
Retrofit分析-漂亮的解耦套路(视频版)
Android:手把手带你 深入读懂 Retrofit 2.0 源码
十.文章索引
Android之网络请求1————HTTP协议
Android之网络请求2————OkHttp的基本使用
Android之网络请求3————OkHttp的拦截器和封装
Android之网络请求4————OkHttp源码1:框架
Android之网络请求5————OkHttp源码2:发送请求
Android之网络请求6————OkHttp源码3:拦截器链
Android之网络请求7————OkHttp源码4:网络操作
Android之网络请求8————OkHttp源码5:缓存相关
Android之网络请求9————Retrofit的简单使用
Android之网络请求10————Retrofit的进阶使用
Android之网络请求11————Retrofit的源码分析
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
