当前位置: 首页 > news >正文

Android OkHttp 源码浅析一

演进之路:原生Android框架不好用 ---- HttpUrlConnect   和 Apache HTTPClient  

第一版  底层使用HTTPURLConnect  

第二版 Square构建 从Android4.4开始

基本使用:

 val okhttp = OkHttpClient()val request = Request.Builder().url("http://www.baidu.com").build()okhttp.newCall(request).enqueue(object : okhttp3.Callback{override fun onFailure(call: okhttp3.Call, e: IOException) {Log.e("--->",e.message!!)}override fun onResponse(call: okhttp3.Call, response: okhttp3.Response) {Log.e("--->",response.body!!.string())}})//enqueue Call接口定义的抽象方法
//newCall RealCall创建出 有三个参数 1 okhttpclient  2.quest originnalRequest 3. forWebSocket //Booleaan
//WebSocket 是通过http创建连接
//

 override fun enqueue(responseCallback: Callback) {check(executed.compareAndSet(false, true)) { "Already Executed" }callStart()
//dispatcher 用来做线程调度 管理 Executor 线程池
//MaxRequests  = 64 最大64个线程  
//MaxRequestPerHost = 5 最多同一主机线程  5client.dispatcher.enqueue(AsyncCall(responseCallback))}override fun isExecuted(): Boolean = executed.get()private fun callStart() {
//跟踪错误分析和记录this.callStackTrace = Platform.get().getStackTraceForCloseable("response.body().close()")
//监听一系列事件 连接建立 断开连接 报文 head body 发送等eventListener.callStart(this)}
@get:Synchronized var maxRequests = 64 最多连接数量 64
@get:Synchronized var maxRequestsPerHost = 5 同一主机 5
internal fun enqueue(call: AsyncCall) {synchronized(this) {readyAsyncCalls.add(call)// Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to// the same host.if (!call.call.forWebSocket) {val existingCall = findExistingCallWithHost(call.host)if (existingCall != null) call.reuseCallsPerHostFrom(existingCall)}}promoteAndExecute()}

同步方法,Deque 双向队列

AsyncCall 共享变量 记录连接数等
if (!call.call.forWebSocket) {//记录数量val existingCall = findExistingCallWithHost(call.host)if (existingCall != null) call.reuseCallsPerHostFrom(existingCall)
}

private fun promoteAndExecute(): Boolean {this.assertThreadDoesntHoldLock()val executableCalls = mutableListOf<AsyncCall>()val isRunning: Booleansynchronized(this) {val i = readyAsyncCalls.iterator()while (i.hasNext()) {val asyncCall = i.next()if (runningAsyncCalls.size >= this.maxRequests) break // Max capacity.if (asyncCall.callsPerHost.get() >= this.maxRequestsPerHost) continue // Host max capacity.i.remove()asyncCall.callsPerHost.incrementAndGet()executableCalls.add(asyncCall)runningAsyncCalls.add(asyncCall)}isRunning = runningCallsCount() > 0}for (i in 0 until executableCalls.size) {val asyncCall = executableCalls[i]asyncCall.executeOn(executorService)}return isRunning}
promoteAndExecute 准备执行函数
readyAsyncCalls 没有执行过的请求 不会超出限制 64 or 5

executableCalls 添加到calls 然后取出遍历 执行 executeOn

val i = readyAsyncCalls.iterator() 遍历被执行的call
if (runningAsyncCalls.size >= this.maxRequests) break // Max capacity.
if (asyncCall.callsPerHost.get() >= this.maxRequestsPerHost) continue // Host max capacity. 超出连接限制的数量 终止请求
i.remove() //移除当前请求
asyncCall.callsPerHost.incrementAndGet()
executableCalls.add(asyncCall) 
runningAsyncCalls.add(asyncCall)

runningAsyncCalls 正在执行的Call

   for (i in 0 until executableCalls.size) {
      val asyncCall = executableCalls[i]

遍历准备执行的call  然后调用executeOn
      asyncCall.executeOn(executorService)
    }

Okhttp enqueue ----> newCall ---> RealCall enqueue ------>  执行 dispatcher . enqueue ---->  添加到readyAsyncCalls ----> promoteAndExecute ---executeOn 执行

  fun executeOn(executorService: ExecutorService) {client.dispatcher.assertThreadDoesntHoldLock()var success = falsetry {executorService.execute(this)success = true} catch (e: RejectedExecutionException) {val ioException = InterruptedIOException("executor rejected")ioException.initCause(e)noMoreExchanges(ioException)responseCallback.onFailure(this@RealCall, ioException)} finally {if (!success) {client.dispatcher.finished(this) // This call is no longer running!}}}

executorService dispatcher 内部类管理的对象 线程调度 参数是runnable

        executorService.execute(this) 线程切换到后台线程 Async 实现了Runnable

线程调度

 override fun run() {threadName("OkHttp ${redactedUrl()}") {var signalledCallback = falsetimeout.enter()try {val response = getResponseWithInterceptorChain()signalledCallback = trueresponseCallback.onResponse(this@RealCall, response)} catch (e: IOException) {if (signalledCallback) {// Do not signal the callback twice!Platform.get().log("Callback failure for ${toLoggableString()}", Platform.INFO, e)} else {responseCallback.onFailure(this@RealCall, e)}} catch (t: Throwable) {cancel()if (!signalledCallback) {val canceledException = IOException("canceled due to $t")canceledException.addSuppressed(t)responseCallback.onFailure(this@RealCall, canceledException)}throw t} finally {client.dispatcher.finished(this)}}}

    val response = getResponseWithInterceptorChain() 获取相应 

getResponseWithInterceptorChain 请求数据的方法封装

responseCallback 代码里声明传入的Callback

http://www.lryc.cn/news/135338.html

相关文章:

  • 【Redis】——Redis基础的数据结构以及应用场景
  • SpringBoot+WebSocket搭建多人在线聊天环境
  • 推荐适用于不同规模企业的会计软件:选择最适合您企业的解决方案
  • Apache Zookeeper架构和选举机制
  • 车联网TCU USB的配置和使用
  • Linux系统USB摄像头测试程序(三)_视频预览
  • 目标检测任务数据集的数据增强中,图像水平翻转和xml标注文件坐标调整
  • 系统架构的演变
  • IDC发布《亚太决策支持型分析数据平台评估》报告,亚马逊云科技位列“领导者”类别
  • C#之OpenFileDialog创建和管理文件选择对话框
  • Java中使用MongoTemplate 简单操作MongoDB
  • [Mac软件]Pixelmator Pro 3.3.12 专业图像编辑中文版
  • 吴恩达 GPT Prompting 课程
  • gpt3.5写MATLAB代码剪辑视频,使之保留画面ROI区域
  • 设计模式二十一:状态模式(State Pattern)
  • 【校招VIP】产品思维能力之产品设计
  • 微信小程序卡片横向滚动竖图
  • SpringBoot项目(支付宝整合)——springboot整合支付宝沙箱支付 从极简实现到IOC改进
  • 【AIGC】一款离线版的AI智能换脸工具V2.0分享(支持图片、视频、直播)
  • 管理类联考——逻辑——真题篇——按知识分类——汇总篇——一、形式逻辑——选言——相容选言——或
  • Git如何操作本地分支仓库?
  • WPS右键新建没有docx pptx xlsx 修复
  • 【巧学C++之西游篇】No.2 --- C++闹天宫,带着“重载“和“引用“
  • 【HarmonyOS】实现将pcm音频文件进行编码并写入文件(API6 Java)
  • KaiwuDB CTO 魏可伟:回归用户本位,打造“小而全”的数据库
  • 行业追踪,2023-08-22
  • 浏览器安装selenium驱动,以Microsoft Edge安装驱动为例
  • 边缘计算网关是如何提高物联网的效率的?
  • AWVS安装~Windows~激活
  • ATFX汇市:杰克逊霍尔年会降至,鲍威尔或再发鹰派言论