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通过使用大量的设计模式进行功能模块的解耦,使得上面的过程更加简单。
具体过程解释如下:
- 通过解析网络请求接口的注解 配置网络请求参数
- 通过动态代理生成网络请求对象
- 通过网络请求适配器将网络请求对象进行平台适配
- 通过网络请求执行器发送网络请求
- 通过数据转换器解析服务器返回的数据
- 通过回调执行器切换线程(子–>主线程)
- 用户在主线程处理返回结果
三.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 { //Java8 Class.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 { //获取与主线程绑定的Handler private 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()后又放入了一个GsonConverterFactory public 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的Call okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); } //配置回调方法执行器 //如果没有指定,则是使用默认的callbackExecutor //即Android默认的callbackExecutor Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { callbackExecutor = platform.defaultCallbackExecutor(); } // Make a defensive copy of the adapters and add the default Call adapter. //配置网络请求适配器工厂 List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories); // 向该集合中添加了步骤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对象 //下面详细分析小标题1 ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method); //作用:根据配置好的serviceMethod对象创建okHttpCall对象 //下面分析 OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);//作用:调用OkHttp,并根据okHttpCall返回rejava的Observe对象或者返回Call return 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) { //下面详细分析ServiceMethod result = 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 baseUrl private 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对象中获取对应的网络请求适配器 -->关注点1 callAdapter = 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对象中获取对应的网络请求//关注点2 return (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 类提供 -->关注点4 return 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 unchecked return (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的实现类
@Override public 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对象交给静态代理delegate this.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对象请求 -->关注1 call = rawCall = createRawCall(); } catch (IOException | RuntimeException | Error e) { throwIfFatal(e); // Do not assign a fatal error to creationFailure. creationFailure = e; throw e; } } } if (canceled) { call.cancel(); } // 步骤2:调用OkHttpCall的execute()发送网络请求(同步) // 步骤3:解析网络请求返回的数据parseResponse() -->关注2 return parseResponse(call.execute()); }
关注1
private okhttp3.Call createRawCall() throws IOException { // 根据serviceMethod和request对象创建 一个okhttp3.Request okhttp3.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>() { //请求成功时回调 @Override public void onResponse(Call<Theaters> call, Response<Theaters> response) { response.body().show(); } //请求失败时回调 @Override public 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.call synchronized (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); } // 获取主线程Handler static 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的源码分析
更多相关文章
- Android消息机制Message消息池
- Android(安卓)Volley 库通过网络获取 JSON 数据
- 在Android中使用Handler和Thread线程执行后台操作
- Android(安卓)Wifi几点
- android adb 查看ip地址命令
- 在android使用mina实现网络访问
- Android(安卓)网络通信——HttpURLConnection
- Android多媒体播放器源码解析(stagefright框架)
- Android(安卓)使用网络技术