Kotlin 中 OkHttp 使用及解析

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")
}*/

参考:

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

相关推荐
モンキー・D・小菜鸡儿6 小时前
Android 中 StateFlow 的使用
android·kotlin
我又来搬代码了6 小时前
【Android】【Compose】Compose知识点复习(一)
android·前端·kotlin·android studio
hnlgzb11 小时前
好像kotlin class和kotlin file都可以是activity?
android·开发语言·kotlin
zhangphil11 小时前
Kotlin超时withTimeout超时与ensureActive()取消协程任务执行
kotlin
hnlgzb20 小时前
安卓app开发,如何快速上手kotlin和compose的开发?
android·开发语言·kotlin
alexhilton20 小时前
Jetpack Compose 2025年12月版本新增功能
android·kotlin·android jetpack
lin62534221 天前
Android九宫格,1张图到9张图适配;图片自定义UI
android·ui·kotlin
zhangphil2 天前
Kotlin协程buffer缓冲池,调度任务执行
kotlin
モンキー・D・小菜鸡儿2 天前
Android Jetpack Compose 基础控件介绍
android·kotlin·android jetpack·compose
侠***I2 天前
基于OOA-TCN-BiGRU-Attention的鱼鹰算法优化多变量时间序列预测
kotlin