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

相关推荐
孤客网络科技工作室6 小时前
AJAX 全面教程:从基础到高级
android·ajax·okhttp
Liknana5 天前
OKHTTP断点续传
android·okhttp·面试
爱编程的鱼8 天前
web前后端交互方式有哪些?
前端·okhttp
鞠崽233339 天前
【六袆 - WebSocket】WebSocket的认识;一次AJAX请求模型;一次长轮询请求模型;一次WebSocket请求模型;
websocket·ajax·okhttp
吃汉堡吃到饱12 天前
【Android】浅析OkHttp(1)
android·okhttp
wa的一声哭了15 天前
黑马JavaWeb-day03
数据结构·c++·人工智能·深度学习·算法·okhttp·eclipse
小R资源15 天前
Django CSRF Token缺失或不正确
okhttp·django·csrf
我就说好玩22 天前
ajax嵌套ajax实现不刷新表单并向指定页面二次提交数据
android·ajax·okhttp
Ther23322 天前
SpringBoot中OKHttp和压缩文件的使用
okhttp
ShyTan23 天前
Java工具类--OkHttp工具类
数据库·okhttp