Android OkHttp 源码浅析一

这篇具有很好参考价值的文章主要介绍了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 最多同一主机线程  5

    client.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: Boolean
    synchronized(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 = false
      try {
        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 = false
        timeout.enter()
        try {
          val response = getResponseWithInterceptorChain()
          signalledCallback = true
          responseCallback.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文章来源地址https://www.toymoban.com/news/detail-666983.html

到了这里,关于Android OkHttp 源码浅析一的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android OkHttp源码阅读详解一

    博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住也分享一下给大家 👉点击跳转到教程 前言:源码阅读基于okhttp:3.10.0 Android中OkHttp源码阅读二(责任链模式) 1、首先回顾OkHttp的使用 2、OkHttp源码阅读之线程池详解 3、守护线程详解 4、根据OkHttp中构

    2024年02月10日
    浏览(38)
  • Android OkHttp源码分析--分发器

    OkHttp是当下Android使用最频繁的网络请求框架,由Square公司开源。Google在Android4.4以后开始将源码中 的HttpURLConnection底层实现替换为OKHttp,同时现在流行的Retrofit框架底层同样是使用OKHttp的。 OKHttp优点: 1、支持Http1、Http2、Quic以及WebSocket; 2、连接池复用底层TCP(Socket),减少请求

    2024年02月13日
    浏览(40)
  • Android Okhttp3 分发器源码解析

    在 OkHttp 中,分发器(Dispatcher)是负责调度和执行网络请求的组件。它 管理 着 并发 的 请求数量 以及请求的 优先级 ,确保合理地使用底层的连接池和线程池,从而 提高 网络请求的 效率 和 性能 。 默认情况下,OkHttp 使用一个单例的分发器,它可以处理同时进行的最大请求

    2024年02月12日
    浏览(45)
  • Android中OkHttp源码阅读二(责任链模式)

    博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住也分享一下给大家 👉点击跳转到教程 Android OkHttp源码阅读详解一 一、首先写一个案例熟悉责任链模式 1、定义一个抽象类BaseTask 2、定义四个Task类,都继承自BaseTask,这里只写一个其它三个同理

    2024年02月10日
    浏览(34)
  • Android---OkHttp详解

    OkHttp 是一套处理 HTTP 网络请求的依赖库,由 Square 公司设计研发并开源,目前可以在 Java 和 Kotlin 中使用。对于 Android App,OkHttp 现在几乎已经占据了所有的网络请求操作。 RetroFit + OkHttp 实现网络请求似乎成了一种标配。 因此,它也是每个 Android 开发工程师的必备技能。了解

    2024年01月19日
    浏览(40)
  • okhttp源码简单流程分析

    拦截器详细解析可以看大佬简书 \\\"https://www.jianshu.com/p/6fac73f7570f\\\"和 “https://www.jianshu.com/p/3c740829475c” okhttp请求流程 1:OkHttpClient okHttpClient = new OkHttpClient.Builder() 构建一个okhttpClient对象,传入你想传入的对象,不传就是默认的; 2:构建request对象 Request request = new Request.Builder(

    2024年02月12日
    浏览(32)
  • Android 使用okhttp监控网络数据

    这里使用Okhttp写了一个demo来监听网络请求过程中的一系列数据,包括当前网络类型、请求体、响应体大小,url,请求方式,当然还有本次核心获取域名解析时长,建立连接时长,保持连接时长,请求总时长这些数据。 一次网络请求经历了哪些过程 通过域名访问的方式来请求

    2024年02月11日
    浏览(44)
  • Android OKhttp使用(下载和上传文件)

    首先在build.gradle中引入okhttp 下面是demo(用okthttp下载网络上的资源) 用okthttp将资源上传至网络

    2024年02月11日
    浏览(50)
  • Android - OkHttp 访问 https 的怪问题

    最近使用 OkHttp 访问 https 请求时,在个别 Android 设备上遇到了几个问题,搜罗网上资料,经过一番实践后,问题得到了解决,同时,我也同步升级了我的 https 证书忽略库 ANoSSL ,在此,对搜集到的资料和问题解决方案做个记录。 文章中的代码实现可到 GitHub 仓库中自行获取:

    2024年04月29日
    浏览(30)
  • [Android]网络框架之OkHttp(详细)(kotlin)

    目录 OkHttp的介绍 添加依赖 OkHttp的使用 get的同步与异步请求 post的同步与异步请求 POST请求的数据格式 POST请求上传文件 POST请求上传json对象 POST请求上传多个数据 OkHttp的配置 1.Builder构建器 2.自定义拦截器 3.自定义缓存 4. 自定义Cookie https://square.github.io/okhttp/ 由Square公司贡献的

    2024年02月12日
    浏览(84)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包