// 模块的 build.gradle
dependencies {
// OkHttp
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
// OkHttp 日志拦截器
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1'
}
// 设置拦截器
val httpLoggingInterceptor = HttpLoggingInterceptor() {
Log.e("okhttp.OkHttpClient", it)
}
// 设置日志拦截器级别,默认为不打印输出日志
httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
// 1.创建 OkHttpClient 对象,其内部也是 new Builder() 然后传到有一个参数的构造方法中
// ,也属于 Builder 模式
okHttpClient = OkHttpClient().newBuilder()
// 设置连接超时为 10 秒
.connectTimeout(10L, TimeUnit.SECONDS)
// 设置文件读取超时为 60 秒
.readTimeout(60L, TimeUnit.SECONDS)
// 设置用于读取和写入缓存响应的响应缓存为 10M
.cache(Cache(cacheDir, 10240 * 1024))
// 设置 http 日志拦截器
// 使用 addInterceptor() 也可以,即为第一层自定义拦截器
// 使用 addNetworkInterceptor() 也可,即为第六层非网页网络拦截拦截器
.addInterceptor(httpLoggingInterceptor)
.build()
// 2.创建 Request 对象,设置一个 url 地址和设置请求方式。
val request = Request.Builder()
.url("https://wanandroid.com/wxarticle/chapters/json")
.get() // 默认 GET 请求,可以不写
.build()
// 3.创建一个 Call 对象,参数就是 Request 请求对象
val call = okHttpClient.newCall(request)
// 4.同步调用会阻塞主线程,这边在子线程进行,较少用
Thread(Runnable {
try {
// 同步调用,返回 Response,会抛出 IO 异常
val response = call.execute()
val data = response.body?.string()
// 注意子线程中不能操作更新 UI
runOnUiThread {
mViewBinding.tvOkhttpText.text = "onResponse: $data"
}
} catch (e: IOException) {
e.printStackTrace()
runOnUiThread {
mViewBinding.tvOkhttpText.text = "onFailure: ${e.message}"
}
}
}).start()
// 4.异步请求加入调度,重写回调方法
call.enqueue(object : Callback {
/**
* 请求成功的回调方法
*
* @param call Call
* @param response Response
*/
override fun onResponse(call: Call, response: Response) {
val data = response.body?.string()
// 注意子线程中不能操作更新 UI
runOnUiThread {
mViewBinding.tvOkhttpText.text = "onResponse: $data"
}
}
/**
* 请求失败的回调方法
*
* @param call Call
* @param e IOException
*/
override fun onFailure(call: Call, e: IOException) {
e.printStackTrace()
runOnUiThread {
mViewBinding.tvOkhttpText.text = "onFailure: ${e.message}"
}
}
})
OkHttpClient
:整个 OkHttp 的核心管理类,所有的内部逻辑和对象归 OkHttpClient 统一来管理,它通过 Builder 构造器生成,构造参数和类成员很多。open class OkHttpClient internal constructor( builder: Builder)
: Cloneable, Call.Factory, WebSocket.Factory {
...
class Builder constructor() {
internal var dispatcher: Dispatcher = Dispatcher() // 任务调度器
internal var connectionPool: ConnectionPool = ConnectionPool()// 连接池
internal val interceptors: MutableList<Interceptor> = mutableListOf()// 整体流程拦截器
internal val networkInterceptors: MutableList<Interceptor> = mutableListOf()// 网络流程拦截器
internal var eventListenerFactory: EventListener.Factory = EventListener.NONE.asFactory()// 流程监听器
internal var retryOnConnectionFailure = true// 连接失败时是否重连
internal var authenticator: Authenticator = Authenticator.NONE// 服务器认证设置
internal var followRedirects = true// 是否重定向
internal var followSslRedirects = true// 是否从 HTTP 重定向到 HTTPS
internal var cookieJar: CookieJar = CookieJar.NO_COOKIES// cookie 设置
internal var cache: Cache? = null// 缓存设置
internal var dns: Dns = Dns.SYSTEM// DNS 设置
internal var proxy: Proxy? = null// 代理设置
internal var proxySelector: ProxySelector? = null// 代理选择器设置
internal var proxyAuthenticator: Authenticator = Authenticator.NONE// 代理服务器认证设置
internal var socketFactory: SocketFactory = SocketFactory.getDefault()// socket 配置
internal var sslSocketFactoryOrNull: SSLSocketFactory? = null// 域名校验
internal var x509TrustManagerOrNull: X509TrustManager? = null// 域名校验
internal var connectionSpecs: List<ConnectionSpec> = DEFAULT_CONNECTION_SPECS// 域名校验
internal var protocols: List<Protocol> = DEFAULT_PROTOCOLS// 协议
internal var hostnameVerifier: HostnameVerifier = OkHostnameVerifier// 域名校验
internal var certificatePinner: CertificatePinner = CertificatePinner.DEFAULT// 域名校验
internal var certificateChainCleaner: CertificateChainCleaner? = null// 域名校验
internal var callTimeout = 0// 默认请求超时时长
internal var connectTimeout = 10_000// 默认连接超时时长
internal var readTimeout = 10_000// 默认读取超时时长
internal var writeTimeout = 10_000// 默认写入超时时长
internal var pingInterval = 0
internal var minWebSocketMessageToCompress = RealWebSocket.DEFAULT_MINIMUM_DEFLATE_SIZE
internal var routeDatabase: RouteDatabase? = null
...
}
Request
:请求参数的配置类,统一采用了 Builder 模式来构造参数(请求 url、请求方法、请求头、请求体)。class Request internal constructor(
@get:JvmName("url") val url: HttpUrl,
@get:JvmName("method") val method: String,
@get:JvmName("headers") val headers: Headers,
@get:JvmName("body") val body: RequestBody?,
internal val tags: Map<Class<*>, Any>
) {
...
open class Builder {
internal var url: HttpUrl? = null// 请求的 url
internal var method: String// 请求方法,如:GET、POST..
internal var headers: Headers.Builder// 请求头
internal var body: RequestBody? = null// 请求体
...
}
Call
:请求调用接口,其内部提供了同步请求、异步请求、取消请求等方法,其具体的实现类为 RealCall
。/**
* 调用是已准备好执行的请求,可以取消请求(已经完成的请求不能被取消)。
* 由于该对象表示单个请求响应对(流),因此不能执行两次。
*/
interface Call : Cloneable {
/** 返回发起此调用的原始请求 */
fun request(): Request
/**
* 同步请求,立即执行
* 抛出两种异常:
* (1)请求失败抛出 IOException;
* (2)如果在执行过一回的前提下再次执行抛出 IllegalStateException。
*/
@Throws(IOException::class)
fun execute(): Response
/**
* 异步请求,会将请求任务加入到对应的队列中再等待执行
* 如果在执行过一回的前提下再次执行抛出 IllegalStateException。
*/
fun enqueue(responseCallback: Callback)
/** 取消请求,已经完成的请求不能被取消 */
fun cancel()
/** 是否已被执行 */
fun isExecuted(): Boolean
/** 是否被取消 */
fun isCanceled(): Boolean
/** 请求超时时间配置 */
fun timeout(): Timeout
public override fun clone(): Call
/** 利用工厂模式来让 OkHttpClient 来创建 Call 对象 */
fun interface Factory {
fun newCall(request: Request): Call
}
}
RealCall
:Call
接口的具体实现类,可以通过OkHttpClient#newCall(request)
创建一个Call
对象。注意:RealCall
有一个内部类AsyncCall
,异步请求就是调用它,它就是一个Runnable
,被调度器中的线程池执行。// OkHttpClient.kt
override fun newCall(request: Request): Call = RealCall(this, request, forWebSocket = false)
class RealCall(
val client: OkHttpClient, val originalRequest: Request,
val forWebSocket: Boolean
) : Call {
...
internal inner class AsyncCall(
private val responseCallback: Callback// 用户传入的响应回调方法
) : Runnable {
// 同一个域名的请求次数,volatile + AtomicInteger 保证在多线程下及时可见性与原子性
@Volatile
var callsPerHost = AtomicInteger(0)
private set
fun reuseCallsPerHostFrom(other: AsyncCall) {
this.callsPerHost = other.callsPerHost
}
val host: String
get() = originalRequest.url.host
val request: Request
get() = originalRequest
val call: RealCall
get() = this@RealCall
fun executeOn(executorService: ExecutorService) {
client.dispatcher.assertThreadDoesntHoldLock()
var success = false
try {
// 调用线程池执行
executorService.execute(this)
success = true
} catch (e: RejectedExecutionException) {
val ioException = InterruptedIOException("executor rejected")
ioException.initCause(e)
noMoreExchanges(ioException)
// 请求失败,调用 Callback.onFailure() 方法
responseCallback.onFailure(this@RealCall, ioException)
} finally {
if (!success) {
// 请求失败,调用调度器 finish() 方法
client.dispatcher.finished(this) // This call is no longer running!
}
}
}
override fun run() {
threadName("OkHttp ${redactedUrl()}") {
var signalledCallback = false
timeout.enter()
try {
// 请求成功,获取到服务器返回的 response 数据
val response = getResponseWithInterceptorChain()
signalledCallback = true
// 调用 Callback.onResponse() 方法,将 response 数据传递出去
responseCallback.onResponse(this@RealCall, response)
} catch (e: IOException) {
if (signalledCallback) {
// 不要两次发出回调信号
Platform.get()
.log("Callback failure for ${toLoggableString()}", Platform.INFO, e)
} else {
// 请求失败,调用 Callback.onFailure() 方法
responseCallback.onFailure(this@RealCall, e)
}
} catch (t: Throwable) {
cancel()
if (!signalledCallback) {
val canceledException = IOException("canceled due to $t")
canceledException.addSuppressed(t)
// 请求失败,调用 Callback.onFailure() 方法
responseCallback.onFailure(this@RealCall, canceledException)
}
throw t
} finally {
// 请求结束,调用调度器 finish() 方法
client.dispatcher.finished(this)
}
}
}
}
...
}
Dispatcher
:调度器,用来调度Call
对象,同时包含一个线程池和三个请求队列(1同2异),用来存放或者执行RealCall/AsyncCall
对象。class Dispatcher constructor() {
// 并发执行的最大请求数
@get:Synchronized
var maxRequests = 64
set(maxRequests) {
require(maxRequests >= 1) { "max < 1: $maxRequests" }
synchronized(this) {
field = maxRequests
}
promoteAndExecute()
}
// 每个主机并发执行的最大请求数
@get:Synchronized
var maxRequestsPerHost = 5
set(maxRequestsPerHost) {
require(maxRequestsPerHost >= 1) { "max < 1: $maxRequestsPerHost" }
synchronized(this) {
field = maxRequestsPerHost
}
promoteAndExecute()
}
/** 正在运行的同步请求队列 */
private val runningSyncCalls = ArrayDeque<RealCall>()
/** 正在运行的异步请求队列 */
private val runningAsyncCalls = ArrayDeque<RealCall.AsyncCall>()
/** 准备执行的异步请求队列 */
private val readyAsyncCalls = ArrayDeque<RealCall.AsyncCall>()
/** 线程池 */
private var executorServiceOrNull: ExecutorService? = null
/**
* 参数1:线程池中核心线程的最大数量;参数2:线程池中允许的最大线程数;
* 参数3:空闲线程的存活时间;参数4:空闲线程存活的时间单位,与 keepAliveTime 配合使用;
* 参数5:阻塞队列;参数6:指定创建线程的工厂;
*
* 该线程池的核心线程数为 0,线程池最有能容纳 Integer.MAX_VALUE 个线程,且线程的空闲存活时间
* 为 60s(可以理解为 okhttp 随时可以创建新的线程来满足需要,可以保证网络的I/O任务有线程来处理
*,不被阻塞),使用的等待队列即 SynchronousQueue。
*
* SynchornousQueue:内部没有任何缓存的阻塞队列。这里表示接到新任务,直接交给线程处理,如果其
* 他的线程都在工作,那就创建一个新的线程来处理这个任务。
*/
@get:Synchronized
@get:JvmName("executorService")
val executorService: ExecutorService
get() {
if (executorServiceOrNull == null) {
executorServiceOrNull = ThreadPoolExecutor(0, Int.MAX_VALUE, 60, TimeUnit.SECONDS,
SynchronousQueue(), threadFactory("$okHttpName Dispatcher", false))
}
return executorServiceOrNull!!
}
}
Callback
:异步请求的回调接口。interface Callback {
/** 请求失败的回调方法 */
fun onFailure(call: Call, e: IOException)
/** 请求成功的回调方法 */
@Throws(IOException::class)
fun onResponse(call: Call, response: Response)
}
Response
:请求返回响应的数据包装类,包含code、message、headers、body等等。class Response internal constructor(...) : Closeable {
...
open class Builder {
internal var request: Request? = null
internal var protocol: Protocol? = null
internal var code = -1
internal var message: String? = null
internal var handshake: Handshake? = null
internal var headers: Headers.Builder
internal var body: ResponseBody? = null
internal var networkResponse: Response? = null
internal var cacheResponse: Response? = null
internal var priorResponse: Response? = null
internal var sentRequestAtMillis: Long = 0
internal var receivedResponseAtMillis: Long = 0
internal var exchange: Exchange? = null
...
}
okhttpClient.newCall(request).execute()
方法进行同步请求时:okhttpClient.newCall(request).equeue()
方法进行异步步请求时:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k8OrcbUZ-1648586078114)(https://note.youdao.com/yws/res/26063/09FE1BC412DC44958231F99730803E98)]
/**
* 参数1:线程池中核心线程的最大数量;参数2:线程池中允许的最大线程数;
* 参数3:空闲线程的存活时间;参数4:空闲线程存活的时间单位,与 keepAliveTime 配合使用;
* 参数5:阻塞队列;参数6:指定创建线程的工厂;
*/
@get:Synchronized
@get:JvmName("executorService")
val executorService: ExecutorService
get() {
if (executorServiceOrNull == null) {
executorServiceOrNull = ThreadPoolExecutor(0, Int.MAX_VALUE, 60, TimeUnit.SECONDS,
SynchronousQueue(), threadFactory("$okHttpName Dispatcher", false))
}
return executorServiceOrNull!!
}
/**
* 参数1:线程池中核心线程的最大数量;参数2:线程池中允许的最大线程数;
* 参数3:空闲线程的存活时间;参数4:空闲线程存活的时间单位,与 keepAliveTime 配合使用;
* 参数5:阻塞队列;参数6:指定创建线程的工厂;
*/
@get:Synchronized
@get:JvmName("executorService")
val executorService: ExecutorService
get() {
if (executorServiceOrNull == null) {
executorServiceOrNull = ThreadPoolExecutor(0, Int.MAX_VALUE, 60, TimeUnit.SECONDS,
SynchronousQueue(), threadFactory("$okHttpName Dispatcher", false))
}
return executorServiceOrNull!!
}