1. OkHttp 简介与基本使用
刚接触 Android 网络请求那会儿,我最先用的其实是 HttpURLConnection —— 每次写起来都像在绣花,又长又容易出错。后来项目里引进了 OkHttp,我才发现原来网络请求可以写得这么清爽。今天我就跟你聊聊 OkHttp 的发展史、它擅长做什么、怎么集成,以及最基础的 GET 和 POST 请求怎么写。
1.1 发展史 – 一个连接协议的进化史
OkHttp 是 Square 公司(就是做 Retrofit、EventBus 那家)早在 2013 年开源的高性能 HTTP 库。我记得当年 Android 4.x 还占主导地位,HttpURLConnection 各种 bug 加上 API 设计蛋疼,Square 直接扔出了这个替代品。为什么它能火?因为 OkHttp 生来就解决了几个痛点:连接复用(避免三次握手反复来)、自动重定向、Gzip 解压、超时控制,而且它天然支持 SPDY 和 HTTP/2。
到现在,OkHttp 已经迭代了 4.x 甚至 5.x(还在预览)。每次升级都不忘向后兼容,这一点我必须给 Square 点赞。其实你现在去看任何主流 Android 项目,只要是涉及到网络请求的,底层十有八九是 OkHttp 在干活。
一点个人经验: 刚开始用 OkHttp 时,我总觉得拦截器没必要,后来有一次线上反馈接口偶发 302 重定向失败,排查了半天才发现是默认的 FollowRedirects 我没关。嗯,从那以后我学乖了 —— 至少要先理解一下 OkHttp 内部有哪些“开关”。
1.2 应用场景 – 它不仅仅是个 HTTP 客户端
说白了,OkHttp 就是为了让你的 App 跟服务器又快又稳地对话。下面这些场景我几乎每天都在用:
- RESTful API 调用:GET 查询、POST 创建、PUT 更新、DELETE 删除,一个 OkHttpClient 全搞定。
- 文件上传 / 下载:配合 MultipartBody 和 ResponseBody,断点续传也不难实现。
- WebSocket 长连接:OkHttp 原生支持 WebSocket,适合聊天、实时推送。
- 拦截器链做无侵入式功能:比如统一加 、打印日志、缓存策略,这些我通常写在拦截器里,而不是每个请求手写。
- 性能测试 / Mock 数据:搭配 MockWebServer(Square 的另一个库)可以轻松模拟服务端响应。
关键结论: 无论你的 App 用什么架构(MVP、MVVM、MVI),网络层最终都绕不开 OkHttp 或它上面的封装(如 Retrofit)。
1.3 集成方式 – 一行依赖的事
在 build.gradle 里加上下面这行就行,记得版本号我习惯用最新稳定版。
dependencies {
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
}
如果你还需要日志打印,再加个日志拦截器:
implementation 'com.squareup.okhttp3:logging-interceptor:4.12.0'
嗯,还有一件事:使用 OkHttp 需要 INTERNET 权限,写在 AndroidManifest.xml 里:
<uses-permission android:name="android.permission.INTERNET" />
注意: 如果你的 App 目标 API 28+ 并且使用明文 HTTP,还需要在 manifest 中配置 android:usesCleartextTraffic="true" 或者在 network_security_config.xml 里单独放行。我曾经因为这个忘记配置,导致线上所有 HTTP 请求直接 404,排查了半小时才发现 —— 很惨,但印象深刻。
1.4 基本 GET 请求 – 同步与异步
OkHttp 的请求流程其实特别线型:构建 Client → 构建 Request → 发起 Call → 处理 Response。
同步 GET 示例:
// 1. 创建全局 OkHttpClient(复用连接池)
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.build();
// 2. 构造 Request
Request request = new Request.Builder()
.url("https://api.example.com/users")
.get()
.build();
// 3. 发起同步请求(会阻塞当前线程)
try {
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
String body = response.body().string();
// 处理数据
}
} catch (IOException e) {
e.printStackTrace();
}
避坑指南: 同步请求不能在主线程执行,否则直接崩溃。我一开始写 demo 时偷懒放在 UI 线程,结果 ANR 警告弹得飞起。异步才是 Android 世界的常态。
异步 GET 示例:
client.newCall(request).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 body = response.body().string();
// 注意:这里在子线程,更新 UI 需要 post 到主线程
}
}
});
1.5 基本 POST 请求 – 表单与 JSON
POST 请求的套路和 GET 差不多,只是多了一个 RequestBody。
提交表单:
RequestBody formBody = new FormBody.Builder()
.add("username", "张三")
.add("password", "123456")
.build();
Request request = new Request.Builder()
.url("https://api.example.com/login")
.post(formBody)
.build();
提交 JSON:
MediaType JSON = MediaType.get("application/json; charset=utf-8");
String json = "{\"username\":\"张三\",\"password\":\"123456\"}";
RequestBody jsonBody = RequestBody.create(json, JSON);
Request request = new Request.Builder()
.url("https://api.example.com/login")
.post(jsonBody)
.build();
你可能会问:每次都要手动拼 JSON 不累吗?没错,所以我后来项目里都上了 Retrofit,它内部默认用 OkHttp,只需写个接口定义就行。但底层原理还是这些,弄明白 OkHttp 的基本用法才能用好上层框架。
1.6 知识结构总览 – 一张图看清 OkHttp
为了帮你快速抓住脉络,我画了一张 OkHttp 的核心请求流程与组件架构。图中包含了客户端、请求、调用、拦截器链、网络层以及响应,你可以看到它们之间的依赖关系。
1.7 本章要点回顾
| 知识点 | 一句话总结 |
|---|---|
| OkHttp 是什么 | Square 开源的 HTTP 客户端,支持 HTTP/2、连接复用、拦截器链 |
| 应用场景 | REST API、文件上传下载、WebSocket、拦截器增强 |
| 集成方式 | 一行 gradle 依赖 + AndroidManifest 中的网络权限 |
| 同步 GET | client.newCall(request).execute()(需子线程) |
| 异步 GET | client.newCall(request).enqueue(callback)(回调在子线程) |
| POST 表单 | 使用 FormBody 构建参数 |
| POST JSON | 使用 RequestBody.create(json, MediaType) |
我的习惯: 会在 Application 中只初始化一个 OkHttpClient 实例,加上连接超时、读超时、写超时以及一个全局的日志拦截器。这样所有请求复用连接池,性能更好,而且统一维护拦截器也方便。你可以在后面的章节看到我是怎么用拦截器处理 自动刷新和重试的。