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执行下一个任务

相关推荐
洛克大航海3 天前
Ajax基本使用
java·javascript·ajax·okhttp
whltaoin9 天前
Java 网络请求 Jar 包选型指南:从基础到实战
java·http·okhttp·网络请求·retrofit
华农第一蒟蒻10 天前
谈谈跨域问题
java·后端·nginx·安全·okhttp·c5全栈
一直向钱11 天前
android 基于okhttp的socket封装
android·okhttp
linuxxx11011 天前
ajax回调钩子的使用简介
okhttp
一直向钱13 天前
android 基于okhttp 封装一个websocket管理模块,方便开发和使用
android·websocket·okhttp
linuxxx11014 天前
ajax() 回调函数参数详解
前端·ajax·okhttp
linuxxx11016 天前
ajax与jQuery是什么关系?
ajax·okhttp·jquery
耀耀_很无聊18 天前
12_OkHttp初体验
okhttp
heeheeai18 天前
okhttp使用指南
okhttp·kotlin·教程