- 沿着使用追溯源码
- Retrofit 的使用过程为:
- 创建 Service 接口
- 创建 Retrofit 对象
- 创建实现了 Service 接口的代理对象
- 调用代理对象的请求方法,发起同步/异步请求并获取回调
- 总结:
- Retrofit 采用动态代理创建实现了 Service 接口的代理对象,当我们调用 service 的请求方法 method 方法时,会执行 InvocationHandler.invoke 方法。在 invoke 方法中,会调用 loadServiceMethod 方法。
- 在 loadServiceMethod 方法内部,如果缓存中已有 method,直接返回对应的 ServiceMethod 对象;否则,会通过大量的反射对方法注解进行解析,生成对应的 ServiceMethod 对象并返回。
- 这里返回的 ServiceMethod 实际上是 SuspendForBody 对象,SuspendForBody 继承于 HttpServiceMethod,HttpServiceMethod 继承于 ServiceMethod。
- 接着调用 ServiceMethod.invoke 方法,会走到 HttpServiceMethod.invoke 方法,在 invoke 方法中,创建 OkHttpCall 对象,并进一步封装成 ExecutorCallbackCall 对象(默认)。实际发起网络请求的就是 OkHttpCall 对象。
- OkHttpCall 发起网络请求,通过 ConverterFactory 将网络请求返回的 Response 数据解析成 Java 对象,并通过 MainThreadExecutor 将回调转发至主线程。
一、疑惑
- 为什么会出现 Retrofit?
1.1. Retrofit 的出现解决了当时使用存在的一些什么问题?
1.2. 使用它有什么便利的地方?
二、使用
- 创建 Service 接口
public interface ApiService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
- 使用
// 1。创建retrofit
val retrofit = Retrofit.Builder().baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
// 2。创建代理对象
val service = retrofit.create(ApiService::class.java)
// 3。调用请求方法
val repos = service.listRepos("octocat")
// 4。发起请求并获取回调
repos.enqueue(object : Callback<List<Repo>> {
override fun onResponse(call: Call<List<Repo>>, response: Response<List<Repo>>) {
LogUtil.e("result: " + response.body())
}
override fun onFailure(call: Call<List<Repo>>, t: Throwable) {
LogUtil.e("onFailure: " + t.toString())
}
})
三、分析
1、创建 Retrofit
- Retrofit 对象的初始化采用了建造者模式
- 涉及了5个对象
- baseUrl
- CallFactory:也就是 OkHttpClient
- Executor:用于线程切换
- CallAdapterFactory:将 OkHttpCall 适配/封装成具体的 Call(copy 话术:对请求的中间过程进行适配的工厂)
- ConverterFactory:对网络请求返回的 Response 数据进行解析
2、创建代理对象
- Retrofit 采用动态代理,创建声明了 Service 接口的实现对象
- 当我们调用 service 的 请求方法时,会执行 InvocationHandler.invoke 方法
- 动态代理具体知识可看:代理模式之动态代理
3、解析请求方法
① Retrofit.validateServiceInterface
- 对定义在 Service 接口中的所有请求方法进行解析
② Retrofit.loadServiceMethod
- 通过 ConcurrentHashMap(线程安全)做 Method——>ServiceMethod 的映射关系存储
- 如果 serviceMethodCache 中已经存在,直接返回对应的 ServiceMethod;否则,进行注解解析
- 因为解析请求方法注解使用了大量的反射操作,所以这里做了缓存工作,即便多次调用统一请求方法,也只需做一次解析工作
ServiceMethod.parseAnnotations
3.1 请求端的信息解析
RequestFactory.parseAnnotations
RequestFactory.parseMethodAnnotation
- 主要是对于方法注解的解析,例如@Header、@GET、@POST等
RequestFactory.parseParameter
- 第一个处,主要是对参数注解的解析
RequestFactory.parseParameterAnnotation
Retrofit.requestBodyConverter
- 对 @Body 注解的解析
- 由于传入的 skipPast 为 null,所以 start = 0。
- 最终使用谁,取决于 factory.requestBodyConverter 方法的返回值是否为 null
3.2 响应端的信息解析
HttpServiceMethod.parseAnnotations
① HttpServiceMethod.createCallAdapter
HttpServiceMethod.callAdapter
- 这里用到了创建 Retrofit 时配置的 CallAdapterFactory
- 由于传入的 skipPast 为 null,所以 start = 0。最终使用谁,取决于获取的 CallAdapter 是否为null
Retrofit.Build.build
- 创建 Retrofit 时 传入的 CallAdapterFactory
Platform.defaultCallAdapterFactories
- 所以 ① 处最后返回的就是 DefaultCallAdapterFactory.get
②
- 以支持 Kotlin 的 suspend function 为例,并且返回值类型不为 Response 类型,那么就会走到 else 分支里,返回 SuspendForBody 对象
至此,对于请求方法的解析已经完毕,都存放到 SuspendForBody 中,接下来我们就可以从实际发起网络请求开始继续往下分析
4、调用请求方法并回调
动态代理的 InvocationHandler
- 找到 Method 方法对应的 ServiceMethod 对象,调用其 invoke 方法
- 在上诉的分析中,我们已经知道了 loadServiceMethod 返回的 ServiceMethod 其实就是 SuspendForBody 对象【SuspendForBody 继承于 HttpServiceMethod,HttpServiceMethod 继承于 ServiceMethod】
- 所以,invoke 方法会走到 HttpServiceMethod 的 invoke 方法
HttpServiceMethod.invoke
- 生成了 OkHttpCall 对象
SuspendForBody
- call:是 HttpServiceMethod.invoke 方法中创建的 OkHttpCall 对象
- callAdapter:是 ① 处中的最后返回的 DefaultCallAdapterFactory.get ,在 ② 处中传入
DefaultCallAdapterFactory.get
- DefaultCallAdapterFactory.get 最后返回的是 ExecutorCallbackCall 对象
- 经过 DefaultCallAdapterFactory 的适配,OkHttpCall 变成了 ExecutorCallbackCall 对象
- isNullable 为 false,最后调用的是 KotlinExtensions.await 方法
KotlinExtensions.await
ExecutorCallbackCall
- delegate 就是 OkHttpCall,ExecutorCallbackCall.enqueue 就会执行到 OkHttpCall.enqueue 方法
OkHttpCall.enqueue
① OkHttpCall.createRawCall
② OkHttpCall.parseResponse
- responseConverter 涉及到 ConverterFactory。那我们熟悉 GsonConverterFactory 举例
GsonConverterFactory
GsonResponseBodyConverter.convert
TypeAdapter.read
- read 方法可以将 JSON 字符串转换成 Java 对象,对网络请求返回的 Response 数据解析成我们声明的对象
③ ExecutorCallbackCall 回调给 OkHttpCall
① Retrofit.Builder.build
① 默认是 Android 平台
- 默认是 Android 平台,生成的 Executor 是 MainThreadExecutor
- 最后会调用到 MainThreadExecutor.execute 方法,利用 handler 切换到主线程
② OkHttpCall 回调给 KotlinExtensions
- resume 方法将执行权交还给挂起点。到此结束!
四、疑惑解答
- 说到为什么会出现 Retrofit,就得看看在 Retrofit 出现前,怎么使用 OkHttp 进行网络请求:
- 我们可以从中知道使用 OkHttp 所存在的一些问题
- 网络请求的接口配置繁琐,需要配置请求头、请求体和请求参数
- 网络请求返回的 Response 数据需要手动解析,且不能够复用
- 无法自动进行线程的切换
-
综上所述,就有了 Retrofit 的出现。Retrofit 是基于 OkHttp 进行的封装。
-
从功能上说,Retrofit 完成了网络请求接口的封装,网络请求返回数据的解析和线程的自动切换,解决了 OkHttp 使用时存在的一些问题
-
从代码结构上说,Retrofit 提供了很多注解,在我们配置网络请求时,简化了代码,且解耦
-
参考资料:
https://blog.csdn.net/xlh1191860939/article/details/108111945?spm=1001.2014.3001.5501
https://www.jianshu.com/p/d99a680e765d