OkHttp深度解析:请求流程、分发器机制、拦截器工作及TCP连接复用

目录

一、OkHttp请求的请求流程是怎样的?

二、OkHttp分发器是怎样工作的?

[2.1 请求队列与线程池维护](#2.1 请求队列与线程池维护)

[2.2 异步请求处理](#2.2 异步请求处理)

[2.3 同步请求处理](#2.3 同步请求处理)

[2.4 请求执行](#2.4 请求执行)

[2.5 请求完成处理:](#2.5 请求完成处理:)

[2.6 线程池设计](#2.6 线程池设计)

三、OkHttp拦截器是如何工作的?

四、应用拦截器和网络拦截器的区别?

[4.1 调用顺序和位置](#4.1 调用顺序和位置)

[4.2 功能和用途](#4.2 功能和用途)

[五、OkHttp 如何复用TCP 连接的?](#五、OkHttp 如何复用TCP 连接的?)

[5.1 具体过程](#5.1 具体过程)

[5.2 优势](#5.2 优势)

相关推荐


一、OkHttp请求的请求流程是怎样的?

java 复制代码
    public void sendOkHttp(){
        //创建OkHttpClient对象
        OkHttpClient client = new OkHttpClient();
        //创建Request
        Request request = new Request.Builder()
                .url("https://shuaici.blog.csdn.net/")
                .build();
        //创建Call对象client.newCall(request)
        Call call = client.newCall(request);
        //通过execute()方法获得请求响应的Response对象
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {}

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if(response.isSuccessful()){
                    String result = response.body().string();
                    //处理UI需要切换到UI线程处理
                }
            }
        });
    }

请求流程总结

  1. 创建OkHttpClient实例:OkHttpClient是OKHttp库的核心类,用于发送HTTP请求和接收HTTP响应。
  2. 创建Request对象:Request对象封装了HTTP请求的所有信息,包括URL、请求方法(GET、POST等)、请求头部和请求体等。
  3. 执行请求:
    1. 通过 OkHttpClient 的 newCall 方法创建 Call 对象。这里的Call是一个接口,实际返回的是它的唯一实现子类RealCall对象。
    2. 同步请求:通过调用call.execute()方法真正发起网络请求,并返回一个Response对象。这种方法会阻塞当前线程,直到请求完成并返回响应。
    3. 异步请求:通过调用call.enqueue(callback)方法真正发起网络请求,并传入一个Callback对象。当请求完成时,OKHttp会自动调用Callback对象的onResponseonFailure方法来处理响应或错误。
  4. 处理响应:在获取到Response对象后,可以通过调用其方法(如body().string())来获取响应体的内容,并进行相应的处理。

二、OkHttp分发器是怎样工作的?

OkHttp分发器(Dispatcher)的主要作用是调配请求任务,它内部维护了队列和线程池来管理请求的执行。以下是OKHttp分发器的工作机制:

2.1 请求队列与线程池维护

  • 分发器内部主要维护了两个队列:readyAsyncCalls(等待执行的异步请求队列)和runningAsyncCalls(正在执行的异步请求队列),以及runningSyncCalls(正在执行的同步请求队列)。
  • 分发器还包含一个线程池executorService,用于执行请求任务。

2.2 异步请求处理

  • 当发起异步请求时,分发器会检查:
  1. 同时请求的异步任务数不得大于64(maxRequests)和
  2. readyAsyncCalls队列中取出异步任务其Host,在runningAsyncCalls中不得大于5。
  3. 则将请求添加到runningAsyncCalls队列并立即执行;如果超过了,则将请求加入到readyAsyncCalls队列中等待。

2.3 同步请求处理

对于同步请求,分发器仅记录请求(放入runningSyncCalls队列中),因为同步请求不需要线程池,也不存在并发限制,所以分发器仅做记录,后续按照加入队列的顺序同步请求即可。

2.4 请求执行

请求执行是通过分发器将任务分配给拦截器链来完成的。拦截器链负责完成网络请求过程,包括请求重试、缓存处理、建立连接等一系列操作。

2.5 请求完成处理:

请求完成后,分发器会从runningAsyncCallsrunningSyncCalls队列中移除对应的请求,并检查是否有等待执行的请求,如果有,则将等待的请求加入到线程池执行

2.6 线程池设计

分发器中的线程池设计为:核心线程数为0,最大线程数为Int.MAX_VALUE,空闲时间为60秒,工作队列为SynchronousQueue()。这种设计意味着,当有任务需要执行时,如果线程池中没有可用线程,会直接创建新线程来处理任务。

三、OkHttp拦截器是如何工作的?

OKHttp的拦截器机制是其核心功能之一,它基于责任链模式实现。每个拦截器都可以处理请求或响应,并将请求或响应传递给下一个拦截器。拦截器的工作机制如下:

  1. 在发起HTTP请求时,OKHttp会依次调用每个拦截器的intercept()方法,将请求传递给下一个拦截器,直到请求被发送到服务器或被拦截器拦截并返回响应为止。
  2. 在接收到响应后,OKHttp会依次调用每个拦截器的intercept()方法,将响应传递给下一个拦截器,直到响应被处理完毕或被拦截器拦截并返回新的响应为止。
  3. 拦截器在处理请求和响应时,可以通过Request和Response对象来获取和修改请求和响应的信息。
java 复制代码
/**
 * 获取响应的拦截器链。
 * 
 * @return Response 对象,包含服务器的响应。
 * @throws IOException 如果发生 I/O 错误。
 */
Response getResponseWithInterceptorChain() throws IOException {
    // 构建完整的拦截器栈。
    List<Interceptor> interceptors = new ArrayList<>();

    // 1. 应用拦截器:用户自定义的拦截器,可以在此拦截器中添加自定义逻辑。
    interceptors.addAll(client.interceptors()); 

    // 2. 重试重定向拦截器:处理请求重试和重定向逻辑。
    interceptors.add(new RetryAndFollowUpInterceptor(client)); 
    // 3. 桥接拦截器:处理请求和响应的转换,例如将请求转换为HTTP/2请求。
    interceptors.add(new BridgeInterceptor(client.cookieJar())); 
    // 4. 缓存拦截器:处理缓存逻辑,决定是否从缓存中读取响应或将响应存储到缓存中。
    interceptors.add(new CacheInterceptor(client.internalCache())); 
    // 5. 连接拦截器:处理与服务器建立连接的逻辑,包括DNS解析和TLS握手。
    interceptors.add(new ConnectInterceptor(client)); 

    // 如果不是WebSocket请求,添加网络拦截器。
    if (!forWebSocket) {
        // 6. 网络拦截器:用户自定义的网络层面的拦截器,可以在此拦截器中添加网络层面的自定义逻辑。
        interceptors.addAll(client.networkInterceptors()); 
    }

    // 7. 服务器调用拦截器:实际向服务器发送请求并接收响应的拦截器,如果是WebSocket请求则特殊处理。
    interceptors.add(new CallServerInterceptor(forWebSocket)); 

    // ......
}

四、应用拦截器和网络拦截器的区别?

4.1 调用顺序和位置

  • 应用拦截器:先经过应用拦截器,再进入内核,再进入网络拦截器。应用拦截器只关心发起的请求和最终得到的结果,不关心重定向或重试等中间响应。
  • 网络拦截器:可以操作重定向或重试的中间响应。如果应用拦截器决定短路并以缓存返回,则网络拦截器就得不到调用。

4.2 功能和用途

  • 应用拦截器:常用于日志记录、身份验证、修改请求或响应等操作。它们可以拦截Chain.proceed()或多次调用Chain.proceed()。
  • 网络拦截器:更侧重于网络层面的操作,如处理重定向、重试策略等。

五、OkHttp 如何复用TCP 连接的?

OkHttp通过其内置的连接池机制高效地复用了TCP连接。连接池会维护一组已经建立的TCP连接,并在需要发送新的HTTP请求时重用这些连接,而不是每次请求都重新建立一个新的TCP连接。

5.1 具体过程

  1. 检查连接池:当OkHttp需要发送一个新的HTTP请求时,它首先会检查连接池中是否有可用的TCP连接。这个检查过程是基于目标服务器的IP地址和端口来进行的。
  2. 复用连接:如果连接池中存在与目标服务器匹配的可用TCP连接,OkHttp就会复用该连接来发送HTTP请求。这意味着,同一个TCP连接上可以发送多个HTTP请求和接收相应的响应,从而减少了每次请求时建立新连接的开销。
  3. 管理连接生命周期:OkHttp会根据配置的参数(如最大空闲连接数、连接空闲超时等)自动管理连接池中的连接。如果某个连接在一段时间内没有被使用,OkHttp会自动将其关闭,以释放系统资源。

5.2 优势

  1. 提高性能:通过复用TCP连接,OkHttp显著减少了连接建立和关闭的开销,从而提高了HTTP请求的响应速度和整体性能。
  2. 减少资源消耗:复用连接可以减少系统资源的消耗,尤其是在高并发的情况下,能够有效减轻服务器的负担。
  3. 降低网络延迟:已经建立的TCP连接可以直接用于发送新的HTTP请求,无需重新进行TCP三次握手等操作,从而降低了网络延迟。

相关推荐

Android OkHttp使用和源码详解-CSDN博客文章浏览阅读1.5k次,点赞10次,收藏5次。OkHttp 是一套处理 HTTP 网络请求的依赖库,由 Square 公司设计研发并开源,目前可以在 Java 和 Kotlin 中使用。对于 Android App 来说,OkHttp 现在几乎已经占据了所有的网络请求操作,RetroFit + OkHttp 实现网络请求似乎成了一种标配。因此它也是每一个 Android 开发工程师的必备技能,了解其内部实现原理可以更好地进行功能扩展、封装以及优化。_com.squareup.okiohttps://shuaici.blog.csdn.net/article/details/120174041Android OkHttp+Retrofit+Rxjava+Hilt实现网络请求框架-CSDN博客文章浏览阅读3.6k次,点赞37次,收藏47次。本文通过OkHttp+Retrofit+Rxjava+Hilt实现一个网络请求框。 最终代码特别省事。_android response.body().getdata()https://shuaici.blog.csdn.net/article/details/121384534

相关推荐
姜行运1 小时前
数据结构【二叉搜索树(BST)】
android·数据结构·c++·c#
JhonKI9 小时前
【MySQL】存储引擎 - CSV详解
android·数据库·mysql
开开心心_Every9 小时前
手机隐私数据彻底删除工具:回收或弃用手机前防数据恢复
android·windows·python·搜索引擎·智能手机·pdf·音视频
大G哥10 小时前
Kotlin Lambda语法错误修复
android·java·开发语言·kotlin
鸿蒙布道师13 小时前
鸿蒙NEXT开发动画案例2
android·ios·华为·harmonyos·鸿蒙系统·arkui·huawei
androidwork13 小时前
Kotlin Android工程Mock数据方法总结
android·开发语言·kotlin
xiangxiongfly91515 小时前
Android setContentView()源码分析
android·setcontentview
人间有清欢16 小时前
Android开发补充内容
android·okhttp·rxjava·retrofit·hilt·jetpack compose
人间有清欢17 小时前
Android开发报错解决
android
每次的天空19 小时前
Android学习总结之kotlin协程面试篇
android·学习·kotlin