type
status
date
slug
summary
tags
category
password
icon

OkHttp 使⽤⽅法简介

  1. 创建⼀个 OkHttp 的实例
    1. 创建 Request
      1. 创建 Call 并发起⽹络请求
         

        OkHttp 源码总结

        • OkHttpClient 相当于配置中⼼,所有的请求都会共享这些配置(例如出错是否重试、共享的连接池)。 OkHttpClient 中的配置主要有:
          • Dispatcher dispatcher :调度器,⽤于调度后台发起的⽹络请求,有后台总请求数和单主机总请求数的控制。
          • ConnectionPool connectionPool :线程池,线程的批量管理,复用。
          • List<Protocol> protocols :⽀持的应⽤层协议,即 HTTP/1.1、HTTP/2 等。
          • List<Interceptor> interceptors :⼤多数时候使⽤的 Interceptor 都应该配置到这⾥。
          • List<Interceptor> networkInterceptors :直接和⽹络请求交互的 Interceptor 配置到这⾥,例如如果你想查看返回的 301 报⽂或者未解压的 Response Body,需要在这⾥看。
          • boolean retryOnConnectionFailure :在请求失败的时候是否⾃动重试。注意,⼤多数的请求失败并不属于 OkHttp 所定义的「需要重试」,这种重试只适⽤于「同⼀个域名的多个 IP 切换重试」「Socket 失效重试」等情况
          • Authenticator authenticator :⽤于⾃动重新认证。配置之后,在请求收到 401 状态码的响应是,会直接调⽤ authenticator ,⼿动加⼊Authorization header 之后⾃动重新发起请求。
          • boolean followRedirects :遇到服务器的重定向的要求是,是否⾃动重定向。
          • boolean followSslRedirects 在重定向时,如果原先请求的是 http ⽽重定向的⽬标是 https,或者原先请求的是 https ⽽重定向的⽬标是 http,是否依然⾃动 follow。(记得,不是「是否⾃动 follow HTTPS URL 重定向的意思,⽽是是否⾃动 follow 在 HTTP 和 HTTPS之间切换的重定向)
          • CookieJar cookieJar :管理 Cookie 的控制器。OkHttp 提供了 Cookie 存取的判断⽀持(即什么时候需要存 Cookie,什么时候需要读取 Cookie,但没有给出具体的存取实现。如果需要存取 Cookie,你得⾃⼰写实现,例如⽤ Map 存在内存⾥,或者⽤别的⽅式存在本地存储或者数据库。
          • Cache cache :Cache 存储的配置。默认是没有,如果需要⽤,得⾃⼰配置出 Cache 存储的⽂件位置以及存储空间上限。
          • List<ConnectionSpec> connectionSpecs:应⽤层⽀持的 Socket 设置,即使⽤明⽂传输(⽤于 HTTP)还是某个版本的 TLS(⽤于 HTTPS)。
          • HostnameVerifier hostnameVerifier :⽤于验证 HTTPS 握⼿过程中下载到的证书所属者是否和⾃⼰要访问的主机名⼀致。
          • CertificatePinner certificatePinner :⽤于设置 HTTPS 握⼿过程中针对某个Host 额外的的 Certificate Public Key Pinner,即把⽹站证书链中的每⼀个证书公钥直接拿来提前配置进 OkHttpClient ⾥去(具体填⼊的是证书的公钥的 hash)值,作为正常的证书验证机制之外的⼀次额外验证。
          • int connectTimeout :建⽴连接(TCP 或 TLS)的超时时间。
          • int readTimeout :发起请求到读到响应数据的超时时间。
          • int writeTimeout :发起请求并被⽬标服务器接受的超时时间。(为什么?因为有时候对⽅服务器可能由于某种原因⽽不读取你的 Request)
        • newCall(Request) ⽅法会返回⼀个 RealCall 对象,它是 Call 接⼝的实现。当调⽤RealCall.execute() 的时候,RealCall.getResponseWithInterceptorChain()会被调⽤,它会发起⽹络请求并拿到返回的响应,装进⼀个 Response 对象并作为返回值返回;RealCall.enqueue() 被调⽤的时候⼤同⼩异,区别在于 enqueue() 会使⽤ Dispatcher 的线程池来把请求放在后台线程进⾏,但实质上使⽤的同样也是 getResponseWithInterceptorChain() ⽅法。
        • getResponseWithInterceptorChain() ⽅法做的事:把所有配置好的 Interceptor 放在⼀个 List ⾥,然后作为参数,创建⼀个RealInterceptorChain 对象,并调⽤ chain.proceed(request) 来发起请求和获取响应。
        • RealInterceptorChain 中,多个 Interceptor 会依次调⽤⾃⼰的 intercept()⽅法。这个⽅法会做三件事:
          • 对请求进⾏预处理
          • 预处理之后,重新调⽤ RealIntercepterChain.proceed() 把请求交给下⼀个 Interceptor
          • 在下⼀个 Interceptor 处理完成并返回之后,拿到 Response 进⾏后续处理
        • 从上到下,每级 Interceptor 做的事:
          • ⾸先是开发者使⽤ addInterceptor(Interceptor) 所设置的,它们会按照开发者的要求,在所有其他 Interceptor 处理之前,进⾏最早的预处理⼯作,以及在收到 Response之后,做最后的善后⼯作。如果你有统⼀的 Header 要添加,可以在这⾥设置;
          • 然后是 RetryAndFollowUpInterceptor :它会对连接做⼀些初始化⼯作,并且负责在请求失败时的重试,以及重定向的⾃动进行后续请求。它的存在,可以让重试和重定向对于开发者是⽆感知的;
          • BridgeInterceptor :它负责⼀些不影响开发者开发,但影响 HTTP 交互的⼀些额外预处理。例如,Content-Length 的计算和添加、gzip 的⽀持(Accept-Encoding: gzip)、gzip 压缩数据的解包,都是发⽣在这⾥;
          • CacheInterceptor :它负责 Cache 的处理。把它放在后⾯的⽹络交互相关 Interceptor 的前⾯的好处是,如果本地有了可⽤的 Cache,⼀个请求可以在没有发⽣实质⽹络交互的情况下就返回缓存结果,⽽完全不需要开发者做出任何的额外⼯作,让 Cache 更加⽆感知;
          • ConnectInterceptor :它负责建⽴连接。在这⾥,OkHttp 会创建出⽹络请求所需要的 TCP 连接(如果是 HTTP),或者是建⽴在 TCP 连接之上的 TLS 连接(如果是 HTTPS),并且会创建出对应的 HttpCodec 对象(⽤于编码解码 HTTP 请求);
          • 然后是开发者使⽤ addNetworkInterceptor(Interceptor) 所设置的,它们的⾏为逻辑和使⽤ addInterceptor(Interceptor) 创建的⼀样,但由于位置不同,所以这⾥创建的 Interceptor 会看到每个请求和响应的数据(包括重定向以及重试的⼀些中间请求和响应),并且看到的是完整原始数据,⽽不是没有加 Content-Length 的请求数据,或者 Body 还没有被 gzip 解压的响应数据。多数情况,这个⽅法不需要被使⽤,不过如果你要做⽹络调试,可以⽤它;
          • CallServerInterceptor :它负责实质的请求与响应的 I/O 操作,即往 Socket ⾥写⼊请求数据,和从 Socket ⾥读取响应数据;
          • notion image

            Okttp中关键类的作用和联系

          • RealCall 其中包含内部类
            •  
          • Dispatcher:调度器
            • 内部包含了线程池去实际的执行任务(RealCall),并通过三个ArrayQueue<AsyncCall> 负责记录 即将执行异步任务正在执行的异步任务 正在执行的同步任务
              💡
              为什么异步任务需要使用两个队列? 参考生产者消费者模型。
          • 拦截器 Interceptor
            • 拦截器链 Chain RealInterceptorChain
            • Exchange
            • RouteSelector
              • RouteSelection
                • Route
              1 大厂面试必问之Okhttp请求复用与缓存方式洋解 2 大厂面试必问之OkHttp连接池复用原理
              💡
              连接池复用原理
              • http1: 同一个连接上面同时只能进行一个请求
                • http2:同一个连接上面可以同时进行多个请求(多路复用)
                判断是否是同一个连接的条件:
                主机、端口号、协议版本、是否使用代理等都相同才可以复用这个连接
                一个新的请求,被封装到RealCall中,在请求时,会走一遍拦截器链,其中连接拦截器是一个单例,所有连接的获取和创建都在里面。
                1. 当这个请求已经具有连接时
                  1. 判断请求具有的连接是否符合当前连接的要求,比如http到https的重定向就不符合要求
                    1. 不符合的需要释放掉当前的连接,走第2步新请求的逻辑
                    2. 符合要求就直接返回请求自己具有的连接。
                1. 当这个请求是一个新请求,还没有连接时
                  1. 尝试重连接池中获取一个不是多路复用的连接,获取到了直接返回
                  2. 通过RouteSelector 选出一组可用的路由(包含直连和代理),不管是否是多路复用的连接,都尝试获取,获取到了直接返回
                  3. 自己创建一个连接
                    1. 然后尝试获取只是多路复用的连接,避免两个可以多路复用的请求,同时创建了两个多路复用的连接,
                      1. 如果发现别的请求已经帮创建好了,就临时存一下自己刚刚创建的连接。以免自己刚刚创建好,别人创建的是个坏的,就可以使用自己创建的。
                    2. 如果上一步没有重复,就把新创建的连接添加到连接池
                3 大厂面试必问之OkHttp责任链模式如何运行的
                4 大厂面试必问之Dispatcher分发流程
              • Dispatcher 的作用:管理请求的分发和调度,控制并发请求数。
              • 同步请求流程:直接执行,完成后从队列中移除。
              • 异步请求流程:根据并发数和主机数决定是否立即执行或放入等待队列。
              • 调度机制:通过 promoteAndExecute() 方法调度等待队列中的请求。
              • 配置参数:可以通过 maxRequestsmaxRequestsPerHost 和 executorService 自定义 Dispatcher 的行为。
              •  
            图形的位置和尺寸测量从 Retrofit 的原理来看 HTTP
            Loading...
            shuouyang
            shuouyang
            android开发 ReactNative开发 小程序开发
            最新发布
            AOSP 环境搭建
            2025-3-29
            View 绘制流程-源码解析
            2025-3-12
            HTTP
            2025-3-4
            JVM 虚拟机
            2025-2-28
            蓝牙-BLE-基础
            2025-2-28
            从 OkHttp 的原理来看 HTTP
            2025-2-19
            公告
            🎉热点信息🎉
            --- 1 ---
            Jet Brains 推出新的跨平台支持 Kotlin MultiPlatform
            --- 2 ---
            新的小巧便捷的依赖注入框架 Koin
            --- 3 ---
            新一代 API 查询语言 GraphQL