build.gradle
dependencies {
//OkHttp
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
}
简单使用例子
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模式来完成初始化,其提供了很多配置参数,每个选项都有默认值。
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 包含了网络请求时的所有请求参数,一共包含以下五个。
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 对象。
/** Prepares the [request] to be executed at some point in the future. */
override fun newCall(request: Request): Call = RealCall(this, request, forWebSocket = false)
call 是一个接口,我们可以将其看做是网络请求的启动器,可用于同步请求异步请求,但重复发起多次请求的话会抛出异常。
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 对象。
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 是一个调度器,用于对全局的网络请求进行缓存调度,其包含一下几个成员变量。
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
其主要逻辑就是通过拦截器来完成整个网络请求过程。
@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 多个拦截器增加串行调用逻辑
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")
}*/
参考:文章来源:https://www.toymoban.com/news/detail-685691.html
https://github.com/leavesCZY/AndroidGuide/blob/master/%E4%B8%BB%E6%B5%81%E5%BC%80%E6%BA%90%E5%BA%93%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%EF%BC%8811%EF%BC%89OkHttp%20%E6%BA%90%E7%A0%81%E8%AF%A6%E8%A7%A3.md文章来源地址https://www.toymoban.com/news/detail-685691.html
到了这里,关于Kotlin 中 OkHttp 使用及解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!