build.gradle
Kotlin
dependencies {
//OkHttp
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
}
简单使用例子
Kotlin
val okHttpClient = OkHttpClient.Builder()
.connectTimeout(Duration.ofSeconds(10))
.readTimeout(Duration.ofSeconds(10))
.writeTimeout(Duration.ofSeconds(10))
.retryOnConnectionFailure(true)
.build()
val request = Request.Builder().url(url).build()
val call = okHttpClient.newCall(request)
call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.e("TAG", "onFailure:${e.message}")
}
override fun onResponse(call: Call, response: Response) {
Log.d("TAG", "onResponse: ${response.body?.string()}")
}
})
1、通过 Builder 模式得到 okHttpClient ,OkHttpClient 包含了对网络请求的全局配置信息,包括链接超时时间、读写超时时间、链接失败重试等配置。
2、通过 Builder 模式得到 request ,Request 包含了本次网络请求的所有请求参数,包括 url、method、headers、body 等。
3、通过 newCall 方法得到 call,Call 就是用于发起请求,可用于执行 **同步请求(execute)、异步请求(enqueue)、取消请求(cancel)**等各种操作。
4、调用 enqueue 方法发起异步请求返回 response ,Response 就包含了此次网络请求的所有返回信息。
5、拿到 Response 对象的 body 并以字符串流的方式进行读取。
一、OkHttpClient
OkHttpClient 使用 Builder模式来完成初始化,其提供了很多配置参数,每个选项都有默认值。
Kotlin
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
internal var cookieJar: CookieJar = CookieJar.NO_COOKIES
internal var cache: Cache? = null
internal var dns: Dns = Dns.SYSTEM
internal var proxy: Proxy? = null
internal var proxySelector: ProxySelector? = null
internal var proxyAuthenticator: Authenticator = Authenticator.NONE
internal var socketFactory: SocketFactory = SocketFactory.getDefault()
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
Request 包含了网络请求时的所有请求参数,一共包含以下五个。
Kotlin
open class Builder {
internal var url: HttpUrl? = null
internal var method: String
internal var headers: Headers.Builder
internal var body: RequestBody? = null
/** A mutable map of tags, or an immutable empty map if we don't have any. */
internal var tags: MutableMap<Class<*>, Any> = mutableMapOf()
}
三、Call
当调用 okHttpClient.newCall(request) 时就会得到一个 call 对象。
Kotlin
/** Prepares the [request] to be executed at some point in the future. */
override fun newCall(request: Request): Call = RealCall(this, request, forWebSocket = false)
call 是一个接口,我们可以将其看做是网络请求的启动器,可用于同步请求异步请求,但重复发起多次请求的话会抛出异常。
Kotlin
interface Call : Cloneable {
/** Returns the original request that initiated this call. */
fun request(): Request
/**
* Invokes the request immediately, and blocks until the response can be processed or is in error.
*
* To avoid leaking resources callers should close the [Response] which in turn will close the
* underlying [ResponseBody].
*
* ```
* // ensure the response (and underlying response body) is closed
* try (Response response = client.newCall(request).execute()) {
* ...
* }
* ```
*
* The caller may read the response body with the response's [Response.body] method. To avoid
* leaking resources callers must [close the response body][ResponseBody] or the response.
*
* Note that transport-layer success (receiving a HTTP response code, headers and body) does not
* necessarily indicate application-layer success: `response` may still indicate an unhappy HTTP
* response code like 404 or 500.
*
* @throws IOException if the request could not be executed due to cancellation, a connectivity
* problem or timeout. Because networks can fail during an exchange, it is possible that the
* remote server accepted the request before the failure.
* @throws IllegalStateException when the call has already been executed.
*/
@Throws(IOException::class)
fun execute(): Response
/**
* Schedules the request to be executed at some point in the future.
*
* The [dispatcher][OkHttpClient.dispatcher] defines when the request will run: usually
* immediately unless there are several other requests currently being executed.
*
* This client will later call back `responseCallback` with either an HTTP response or a failure
* exception.
*
* @throws IllegalStateException when the call has already been executed.
*/
fun enqueue(responseCallback: Callback)
/** Cancels the request, if possible. Requests that are already complete cannot be canceled. */
fun cancel()
/**
* Returns true if this call has been either [executed][execute] or [enqueued][enqueue]. It is an
* error to execute a call more than once.
*/
fun isExecuted(): Boolean
fun isCanceled(): Boolean
/**
* Returns a timeout that spans the entire call: resolving DNS, connecting, writing the request
* body, server processing, and reading the response body. If the call requires redirects or
* retries all must complete within one timeout period.
*
* Configure the client's default timeout with [OkHttpClient.Builder.callTimeout].
*/
fun timeout(): Timeout
/**
* Create a new, identical call to this one which can be enqueued or executed even if this call
* has already been.
*/
public override fun clone(): Call
fun interface Factory {
fun newCall(request: Request): Call
}
}
ReallCall 是 Call 接口的唯一实现类
当调用 execute 方法发起同步请求时,
1、判断是否重复请求。
2、时间记录。
3、将自身加入到 dispatcher 中,并在请求结束时从 dispatcher 中移除自身。
4、通过 getResponseWithInterceptorChain 方法得到 response 对象。
Kotlin
override fun execute(): Response {
check(executed.compareAndSet(false, true)) { "Already Executed" }
timeout.enter()
callStart()
try {
client.dispatcher.executed(this)
return getResponseWithInterceptorChain()
} finally {
client.dispatcher.finished(this)
}
}
四、Dispatcher
Dispatcher 是一个调度器,用于对全局的网络请求进行缓存调度,其包含一下几个成员变量。
Kotlin
var maxRequests = 64
var maxRequestsPerHost = 5
/** Ready async calls in the order they'll be run. */
private val readyAsyncCalls = ArrayDeque<AsyncCall>()
/** Running asynchronous calls. Includes canceled calls that haven't finished yet. */
private val runningAsyncCalls = ArrayDeque<AsyncCall>()
/** Running synchronous calls. Includes canceled calls that haven't finished yet. */
private val runningSyncCalls = ArrayDeque<RealCall>()
1、maxRequests 同一时间允许并发执行网络请求的最大线程数。
2、maxRequestsPerHost 同一个 host 下的最大同时请求数。
3、readyAsyncCalls 保存当前等待执行的异步任务
4、runningAsyncCalls 保存当前正在执行的异步任务。
5、runningSyncCalls 保存等钱正在执行的同步任务。
五、getResponseWithInterceptorChain
其主要逻辑就是通过拦截器来完成整个网络请求过程。
Kotlin
@Throws(IOException::class)
internal fun getResponseWithInterceptorChain(): Response {
// Build a full stack of interceptors.
val interceptors = mutableListOf<Interceptor>()
interceptors += client.interceptors
interceptors += RetryAndFollowUpInterceptor(client)
interceptors += BridgeInterceptor(client.cookieJar)
interceptors += CacheInterceptor(client.cache)
interceptors += ConnectInterceptor
if (!forWebSocket) {
interceptors += client.networkInterceptors
}
interceptors += CallServerInterceptor(forWebSocket)
val chain = RealInterceptorChain(
call = this,
interceptors = interceptors,
index = 0,
exchange = null,
request = originalRequest,
connectTimeoutMillis = client.connectTimeoutMillis,
readTimeoutMillis = client.readTimeoutMillis,
writeTimeoutMillis = client.writeTimeoutMillis
)
var calledNoMoreExchanges = false
try {
val response = chain.proceed(originalRequest)
if (isCanceled()) {
response.closeQuietly()
throw IOException("Canceled")
}
return response
} catch (e: IOException) {
calledNoMoreExchanges = true
throw noMoreExchanges(e) as Throwable
} finally {
if (!calledNoMoreExchanges) {
noMoreExchanges(null)
}
}
}
六、interceptor
interceptor 多个拦截器增加串行调用逻辑
Kotlin
package com.gxx
class Request
class Response
interface Chain {
fun request(): Request
fun proceed(request: Request): Response
}
interface Interceptor {
fun intercept(chain: Chain): Response
}
class RealInterceptorChain(
private val request: Request,
private val interceptors: List<Interceptor>,
private val index: Int
) : Chain {
private fun copy(index: Int): RealInterceptorChain {
return RealInterceptorChain(request, interceptors, index)
}
override fun request(): Request {
return request
}
override fun proceed(request: Request): Response {
val next = copy(index + 1)
val interceptor = interceptors[index]
return interceptor.intercept(next)
}
}
class LogInterceptor : Interceptor {
override fun intercept(chain: Chain): Response {
val request = chain.request()
println("LogInterceptor -- getRequest")
val response = chain.proceed(request)
println("LogInterceptor ---- getResponse")
return response
}
}
class HeaderInterceptor : Interceptor {
override fun intercept(chain: Chain): Response {
val request = chain.request()
println("HeaderInterceptor -- getRequest")
val response = chain.proceed(request)
println("HeaderInterceptor ---- getResponse")
return response
}
}
class CallServerInterceptor : Interceptor {
override fun intercept(chain: Chain): Response {
val request = chain.request()
println("CallServerInterceptor -- getRequest")
val response = Response()
println("CallServerInterceptor ---- getResponse")
return response
}
}
fun main() {
val interceptorList = mutableListOf<Interceptor>()
interceptorList.add(LogInterceptor())
interceptorList.add(HeaderInterceptor())
interceptorList.add(CallServerInterceptor())
val request = Request()
val realInterceptorChain = RealInterceptorChain(request, interceptorList, 0)
val response = realInterceptorChain.proceed(request)
println("main response")
}
/*
fun main() {
val interceptorList = mutableListOf<Interceptor>()
interceptorList.add(LogInterceptor())
interceptorList.add(HeaderInterceptor())
val request = Request()
val realInterceptorChain = RealInterceptorChain(request, interceptorList, 0)
val response = realInterceptorChain.proceed(request)
println("main response")
}*/
参考: