OkHttp

OkHttp是一个用于Android和Java应用的高效HTTP客户端库。它具有以下优点:

优点

  1. 高效连接池
    • 支持连接复用(Connection Pooling)减少延迟。
    • 有效管理HTTP/2多路复用。
  2. 透明压缩
    • 自动处理Gzip压缩,减少传输的数据量。
  3. 缓存响应
    • 内置缓存机制,帮助减少不必要的网络调用,提高速度和节省流量。
  4. 异步请求
    • 支持异步请求,避免阻塞主线程,提高应用响应速度。
  5. 支持WebSocket
    • 提供WebSocket支持,便于实时通信。
  6. 安全性
    • 支持TLS加密,确保数据传输的安全性。
  7. 易于集成和使用
    • 简单的API设计,方便与其他库(如Retrofit)集成。

简单使用

  1. 依赖
java 复制代码
    implementation("com.squareup.okhttp3:okhttp:4.9.3")
    implementation("com.google.code.gson:gson:2.8.8")
  1. 定义json转换的对象
kotlin 复制代码
data class ImageData(
    val createTime: Long,
    val id: Long,
    val name: String,
    val path: String,
    val size: Long
)

data class ApiResponse(
    val data: List<ImageData>,
    val errorCode: Int,
    val isSuccess: Boolean
)
  1. 直接调用即可,主要在接收到后使用Gson反序列化。
kotlin 复制代码
class OkHttpActivity : AppCompatActivity() {
    private lateinit var binding: ActivityOkHttpBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityOkHttpBinding.inflate(layoutInflater)
        setContentView(binding.root)
        binding.recyclerView.layoutManager = LinearLayoutManager(this)
        fetchData()
    }
    private fun fetchData() {
        val client = OkHttpClient()
        val request = Request.Builder()
            .url("http://192.168.42.7:9876/image/listImage?page=0&pageSize=100")
            .build()

        client.newCall(request).enqueue(object : okhttp3.Callback {
            override fun onFailure(call: okhttp3.Call, e: IOException) {
                e.printStackTrace()
            }

            override fun onResponse(call: okhttp3.Call, response: okhttp3.Response) {
                response.body?.string()?.let { jsonString ->
                    val apiResponse = Gson().fromJson(jsonString, ApiResponse::class.java)
                    runOnUiThread {
                        binding.recyclerView.adapter = ImageAdapter(apiResponse.data)
                    }
                }
            }
        })
    }
}

效果

拦截器

  1. RetryAndFollowUpInterceptor:重试+重定向

    • 直接放行,在调用后才会去执行
    • 根据retryOnConnectionFailure属性、请求体类型判断是否重试
    • 重试无次数限制,重定向20次
  2. BridgeInterceptor

    • 对用户请求进行预处理,添加必要的请求头信息,如Content-Type、Content-Length、Host、Connection、Accept-Encoding(如果用户未指定则添加gzip支持)、Cookie(如果有)和User-Agent(如果用户未指定)。
    • 处理网络响应,包括处理透明的 gzip 压缩响应,解压 gzip 压缩的响应体并更新响应头,去除Content-Encoding和Content-Length头信息,并使用新的响应体。
    • 负责将请求的 Cookie 发送到服务器,并接收服务器返回的 Cookie 更新本地的 CookieJar。
  3. CacheInterceptor(只对get有效,需要配置cache)(DiskLruCache)

    • 配置
    java 复制代码
      val builder = OkHttpClient.Builder()
      builder.cache(Cache(File(""),1000))
  4. ConnectInterceptor

    • 建立与服务器的连接并初始化数据交换对象,然后继续沿着拦截器链执行后续的处理步骤。
    • 得到一个链接后传给下一层(connectionPool)
  5. CallServerInterceptor

    • 负责将参数封装到request
    • 将结果封装到response
    • Expect: 100-continue,大容量请求或验证

原理

okhttp(传输层)
  1. Deque(双端队列)
    等待队列
    private val readyAsyncCalls = ArrayDeque()
    异步队列
    private val runningAsyncCalls = ArrayDeque()
    同步队列
    private val runningSyncCalls = ArrayDeque()
  2. running队列数量<64,并且同时访问同一个host数量<5,就直接加入running队列,否则则加入等待队列
    4.9.3版本:直接加入readyAsyncCalls队列,call.callsPerHost指向同一个AtomicInteger,原子计数。
    maxRequests = 64,maxRequestsPerHost = 5在取出时考虑
kotlin 复制代码
  internal fun enqueue(call: AsyncCall) {
    synchronized(this) {
      readyAsyncCalls.add(call)
      if (!call.call.forWebSocket) {
        val existingCall = findExistingCallWithHost(call.host)
        if (existingCall != null) call.reuseCallsPerHostFrom(existingCall)//PerHostFrom原子计数
      }
    }
    promoteAndExecute()
  }
  1. 基于第二点的控制,所以线程池不设置等待队列,使用SynchronousQueue无容量队列,且最大线程数无限,核心为0
kotlin 复制代码
        executorServiceOrNull = ThreadPoolExecutor(0, Int.MAX_VALUE, 60, TimeUnit.SECONDS,
            SynchronousQueue(), threadFactory("$okHttpName Dispatcher", false))
  1. 执行结束后移除队列,并执行回调
kotlin 复制代码
  private fun <T> finished(calls: Deque<T>, call: T) {
    val idleCallback: Runnable?
    synchronized(this) {
      if (!calls.remove(call)) throw AssertionError("Call wasn't in-flight!")
      idleCallback = this.idleCallback
    }

    val isRunning = promoteAndExecute()

    if (!isRunning && idleCallback != null) {
      idleCallback.run()
    }
  }
  1. 构建者模式,责任链模式

  2. connectInteceptor创建socket请求

  3. ConnectionPool,设置线程池为守护线程

    • 避免阻止 JVM 正常退出。
    • 更高效地管理后台任务和连接。
    • 自动清理资源,防止资源泄漏。
  4. promoteCalls执行下一个任务

相关推荐
Code额2 小时前
认识 Promise
okhttp·promise
ps酷教程2 天前
OkHttp&HttpClient
okhttp·httpclient
东东__net6 天前
27_promise
okhttp
阿湯哥6 天前
SSE SseEmitter.completeWithError(e) 触发的处理逻辑
okhttp
每次的天空11 天前
Android第六次面试总结(okhttp篇)
android·okhttp
胡图蛋.13 天前
AJAX的理解和原理还有概念
okhttp
Blue.ztl14 天前
Ajax与Axios,以及Apifox的入门使用
前端·ajax·okhttp
字节王德发16 天前
为什么Django能有效防御CSRF攻击?
okhttp·django·csrf
逆风飞翔的小叔19 天前
【微服务】java中http调用组件深入实战详解
okhttp·httpclient·resttemplate·http组件详解·httpclient详解
Rverdoser23 天前
封装AJAX(带详细注释)
okhttp