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

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文件

此时,依赖配置完毕,同步一下

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

java 复制代码
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,通常只会另外开辟线程使用或者用于测试代码

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

java 复制代码
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

相关推荐
用户20187928316730 分钟前
<include>标签时设置ltr无效?
android
用户20187928316734 分钟前
Android多语言与RTL/LTR适配
android
码间舞1 小时前
【面试官】:如何解决多个请求失败后重复弹窗报错
前端·javascript·面试
慕晨2 小时前
升级到Android 15+ 以后如何适配Edge-To-Edge?
android
用户2018792831672 小时前
解析:Android Drawable目录的屏幕密度适配原理
android
Java水解2 小时前
Spring Boot 全局异常处理与日志监控实战
后端·面试
KanS13 小时前
2025 运营岗位-阿里面试题分析
面试·产品运营
pengyu3 小时前
【Kotlin系统化精讲:柒】 | 数据类型之复合及高级数据类型:构建复杂程序的万能钥匙
android·kotlin
xzkyd outpaper3 小时前
Kotlin 协程启动方式
android·开发语言·kotlin