Retrofit 核心源码分析(三)- Call 逻辑分析和扩展机制
在前面的两篇文章中,我们已经对 Retrofit 的注解解析、动态代理、网络请求和响应处理机制有了一定的了解。在这篇文章中,我们将深入分析 Retrofit 的 Call 逻辑,并介绍 Retrofit 的扩展机制。
一、Call 逻辑分析
Call 是 Retrofit 中最基本的操作单元,它代表一个 HTTP 请求。在 Retrofit 中,我们通过接口定义请求的方式,并通过动态代理生成接口的实现类。这个实现类中的方法都会返回一个 Call 对象,通过这个对象我们可以发起网络请求,并获得响应结果。
Retrofit 的 Call 逻辑可以用以下代码来描述:
1 |
|
在这个接口中,我们可以看到 Retrofit 定义了五个方法,分别是 execute
、enqueue
、cancel
、isExecuted
和isCanceled
。我们来逐一分析这些方法的作用。
execute 方法
execute
方法用于同步发起 HTTP 请求,当我们调用execute()
方法时,它会立即发起网络请求,并且阻塞当前线程直到请求结束,最后返回一个响应对象Response
。这种方式适用于简单的网络请求,但不适合于在主线程中执行请求,因为会阻塞 UI 线程。
以下是execute()
方法的部分代码:
1 |
|
上述代码中,我们可以看到该方法首先会检查当前请求是否已经执行过,如果已经执行过则会抛出一个异常。然后会将该请求加入到Dispatcher
中的执行队列中。接下来会调用getResponseWithInterceptorChain()
方法来获取响应结果。如果结果为null,则表示请求已经被取消,否则返回响应结果。最后,会将该请求从执行队列中移除。
enqueue 方法
enqueue
方法用于异步发起 HTTP 请求,它会在后台线程中发起网络请求,并在请求结束后将结果返回到主线程中。因此,enqueue()
方法适用于在主线程中执行网络请求。
以下是enqueue()
方法的部分代码:
1 |
|
上述代码中,我们可以看到该方法首先会检查当前请求是否已经执行过,如果已经执行过则会抛出一个异常。然后会将该请求封装成一个AsyncCall
对象,加入到Dispatcher
中的异步队列中。
AsyncCall
继承自RealCall
,它实现了Runnable
接口,表示可以在后台线程中执行。在AsyncCall
中,我们可以看到它会在后台线程中执行网络请求,并将结果通过Callback
回调返回到主线程中。
1 |
|
在AsyncCall
中,首先会调用getResponseWithInterceptorChain()
方法来获取响应结果。如果请求被取消,则会调用onFailure()
方法将结果返回到主线程中。否则,会调用onResponse()
方法将结果返回到主线程中。无论请求成功或失败,都会调用finished()
方法将该请求从异步队列中移除。
cancel 方法
cancel
方法用于取消正在执行的请求。如果请求已经完成或已经取消,则该方法不会有任何效果。
isExecuted 方法
isExecuted
方法用于判断请求是否已经执行。如果已经执行,则返回true,否则返回false。
isCanceled 方法
isCanceled
方法用于判断请求是否已经取消。如果已经取消,则返回true,否则返回false。
clone 方法
clone
方法用于创建一个当前 Call 对象的副本。这个方法一般用于发起多次相同的请求。
以上这些方法就构成了 Retrofit 的 Call 逻辑。在使用 Retrofit 时,我们一般会通过execute
或enqueue
方法发起 HTTP 请求,并通过传入的Callback
对象来处理响应结果。
二、扩展机制
Retrofit 是一个非常灵活的网络请求库,它提供了很多扩展机制,让我们可以根据自己的需要来定制请求和响应处理逻辑。下面介绍一些常用的扩展机制。
Converter
Converter 用于将 HTTP 请求和响应的数据类型转换成 Java 对象。Retrofit 默认提供了两种 Converter:GsonConverter
和JacksonConverter
,它们分别使用Gson
和Jackson
库将数据类型转换成Java
对象。如果我们需要使用其他类型的转换库,也可以自定义 Converter 来实现。
下面是一个自定义 Converter 的示例:
1 |
|
在上面的示例中,我们定义了一个MyConverter
类,它实现了Converter
接口,用于将ResponseBody
类型的响应数据转换成MyObject
类型的Java
对象。在convert
方法中,我们使用自己定义的转换逻辑来实现数据类型的转换。
Interceptor
Interceptor 用于对 HTTP 请求进行拦截和处理。在 Retrofit 中,我们可以通过 Interceptor 来对请求添加头信息、对响应进行缓存、打印请求日志等操作。Retrofit 提供了两种 Interceptor:OkHttpInterceptor
和RetrofitInterceptor
,它们分别用于拦截 OkHttp 的请求和 Retrofit 的请求。我们也可以自定义 Interceptor 来实现自己的拦截逻辑。
下面是一个自定义 Interceptor 的示例:
1 |
|
在上面的示例中,我们定义了一个MyInterceptor
类,它实现了Interceptor
接口,用于对请求和响应进行拦截和处理。在intercept
方法中,我们可以对请求进行处理,然后使用chain.proceed(request)
方法将请求传递给下一个拦截器或处理器,最终获得响应结果并进行处理。
CallAdapter
CallAdapter 用于将 Call 对象转换成另一种类型的对象。在 Retrofit 中,我们可以通过 CallAdapter 将 Call 对象转换成 RxJava 的 Observable 对象,也可以将 Call 对象转换成 LiveData 对象。Retrofit 提供了两种CallAdapter:RxJavaCallAdapter
和LiveDataCallAdapter
,它们分别用于将 Call 对象转换成 RxJava 的 Observable 对象和 LiveData 对象。我们也可以自定义 CallAdapter 来实现自己的转换逻辑。
下面是一个自定义 CallAdapter 的示例:
1 |
|
在上面的示例中,我们定义了一个MyCallAdapter
类,它实现了CallAdapter
接口,用于将Call
对象转换成MyResult
对象。在responseType
方法中,我们返回了响应数据的类型,它是一个ParameterizedTypeImpl
类型的对象,用于表示MyResult<T>
类型。在adapt
方法中,我们对Call
对象进行处理,并返回自定义的MyResult
对象,它包含了响应数据、状态码和错误信息。
总结
在本文中,我们深入分析了 Retrofit 的核心源码,特别是 Call 逻辑的实现细节,以及 Retrofit 的三个扩展机制:Converter、Interceptor 和 CallAdapter。
通过本文的学习,我们可以更加深入地理解 Retrofit 的工作原理,并可以根据需求自定义扩展 Retrofit 的功能。同时,本文提供了三个扩展机制的示例代码,可以帮助读者更加深入地了解 Retrofit 的扩展机制的使用。