第一章 OkHttp 是怎么发出一个请求的?——整体流程概览

发布于:2025-08-15 ⋅ 阅读:(16) ⋅ 点赞:(0)

OkHttp相关的内容往往会在面试的过程中被一再提及,那么,OkHttp 到底是怎么把一句话 “帮我请求一下百度” 变成一次真正的网络通信?我们一步步来看吧

本章主要目标:
简单了解OkHttp的主体结构以及使用

1、场景想象

大家应该都点过外卖吧,我们不妨用外卖的视角来看下OkHttp的登场角色以及作用过程

OkHttp 概念 外卖实体 真实动作 映射
OkHttpClient 外卖平台总部 拥有全部运力、系统、客服、仓库 全局配置、连接池、线程池
Request 下单小票 用户 App 里下订单,含取货地址+送货地址+备注 URL、Header、Body
Call 一次“跑腿单” 平台生成唯一单号,可立即派送或排队 RealCall
Dispatcher 外卖调度中心 最多可派64辆车,每栋楼最多派5辆 runningAsyncCalls / perHost limit
ConnectionPool 电动车停靠点 刚送完 A 栋的电动车不返仓,直接停楼下接下一单,5 分钟没人叫才回仓 空闲连接 5 分钟回收
Interceptor 链 5 道检查口 ①重试口(地址错?重派)
②加料口(默认给筷子)
③缓存口(店里现成?直接拿)
④取车口(给电动车)
⑤出单口(打印小票)
5 大拦截器
Response 骑手送达后拍的照片+回执 用户点确认收货,平台回传“已送达”照片 Response 对象

2、流程概览

依照先前的设定,先简单借助图了解一下大概的流程,接着一步步拆解整个的过程
在这里插入图片描述
①首先,我们需要创建一个okHttpClient,这是一切的前提
②接着,作为客户,我们需要下单,此时Request便产生了,Request肯定需要一些我们的信息
newCall给到okHttpClient,那么就会借助Call,生成订单
④接下来,平台进行调度,Dispatcher给了两种方式,对应executeenqueue两种方式
⑤快递员出发需要层层检查,通过Interceptors来处理
⑥最终快递员将外卖送到用户手上或者放在门口拍照打卡,完成一次完整请求

3、代码层面

现在可能你对整个流程有更加生动的认识了,接下来,我们通过代码再来加深认识
这里我使用的是3.9.0的版本
build.gradle里面进行一下配置,好像现在的版本还有一个toml文件
在这里插入图片描述
在这里插入图片描述
此时,依赖配置完毕,同步一下

首先,看看我们平常直接使用的代码,仅仅是发起一个请求

try {                                                                                                              
    OkHttpClient okHttpClient = new OkHttpClient();                                                                
    Request request = new Request.Builder()                                                                        
            .url("https://movie.douban.com/j/chart/top_list?type=10&interval_id=100%3A90&action&start=20&limit=20")
            .build();                                                                                              
                                                                                                                   
    // 使用try-with-resources自动关闭Response,避免内存泄漏                                                                     
    try (Response response = okHttpClient.newCall(request).execute()) {                                            
        Log.d(TAG, "response=\n" + response.body().string());                                                      
    }                                                                                                              
} catch (Exception e) {                                                                                            
    e.printStackTrace();                                                                                           
}                                                                                                                  

这便是同步请求的写法,使用execute()进行请求
创建了OkHttpClient对象,并且给Request添加了信息,这里使用的是豆瓣电影的接口
使用newCall()创建请求,执行结果给到Response
注意,同步请求会阻塞当前的线程,直到结果返回,因此不会在主线程调用,否则很容易造成ANR,通常只会另外开辟线程使用或者用于测试代码

有一个初步的印象,我们再来看一看异步请求

OkHttpClient okHttpClient = new OkHttpClient();                                                                
Request request = new Request.Builder()                                                                        
        .url("https://movie.douban.com/j/chart/top_list?type=10&interval_id=100%3A90&action&start=20&limit=20")
        .build();                                                                                              
okHttpClient.newCall(request).enqueue(new Callback() {                                                         
    @Override                                                                                                  
    public void onFailure(Call call, IOException e) {                                                          
        e.printStackTrace();                                                                                   
    }                                                                                                          
                                                                                                               
    @Override                                                                                                  
    public void onResponse(Call call, Response response) throws IOException {                                  
        try {                                                                                                  
            Log.d(TAG, "response=\n" + response.body().string());                                              
        } finally {                                                                                            
            response.close(); // 确保Response被关闭                                                                 
        }                                                                                                      
    }                                                                                                          
});                                                                                                                                                                                                                        

同样的业务需求,使用enqueue()则进行异步请求,不会阻塞,获得响应时回调
通常情况下都是采用异步请求的方式

在这里插入图片描述
这便是最简单的使用,通过response.body().string()获取响应结果

这两者主要的区别,在于是调用了execute()还是调用了equeue(),后面几章将会深入探讨里面的内容

参考
https://github.com/square/okhttp


网站公告

今日签到

点亮在社区的每一天
去签到