OkHttp 拦截器工作原理
OkHttp 的拦截器(Interceptor)是其核心特性之一,它允许你在请求发送前或响应返回后对数据进行拦截和处理。这种机制为日志记录、请求参数修改、缓存处理等功能提供了强大的扩展能力。
拦截器的工作流程
OkHttp 的拦截器采用责任链模式(Chain of Responsibility),形成一个有序的拦截器链。当发起一个请求时,请求会依次通过每个拦截器的处理,最终到达服务器;响应返回时,则按相反顺序再次经过拦截器链。
拦截器链分为两个主要部分:
- 应用拦截器(Application Interceptors):由用户显式添加的拦截器,位于链条前端。
- 网络拦截器(Network Interceptors):由 OkHttp 内部添加的拦截器,负责处理与网络相关的操作,位于链条后端。
拦截器接口与关键方法
拦截器需要实现 Interceptor 接口,主要方法是 intercept(Chain chain):
public interface Interceptor {
Response intercept(Chain chain) throws IOException;
interface Chain {
Request request(); // 获取当前请求
Response proceed(Request request) throws IOException; // 将请求传递给下一个拦截器
Connection connection(); // 获取网络连接信息(仅网络拦截器可用)
}
}
在 intercept 方法中,你可以:
- 修改请求(如添加 headers、参数)
- 记录请求日志
- 提前返回响应(如使用缓存)
- 处理响应(如解密、解析数据)
- 捕获异常并进行重试
拦截器链的执行顺序
典型的拦截器链执行顺序如下:
- 用户添加的应用拦截器(按添加顺序执行)
- RetryAndFollowUpInterceptor:处理失败重试和重定向
- BridgeInterceptor:将用户的请求转换为网络请求(如添加默认 headers)
- CacheInterceptor:处理缓存逻辑
- ConnectInterceptor:建立网络连接
- 用户添加的网络拦截器(按添加顺序执行)
- CallServerInterceptor:向服务器发送请求并接收响应
应用拦截器 vs 网络拦截器
| 特性 | 应用拦截器 | 网络拦截器 |
|---|---|---|
| 添加方式 | client.addInterceptor() | client.addNetworkInterceptor() |
| 执行位置 | 拦截器链前端 | 拦截器链后端(网络层) |
| 可见范围 | 原始请求和最终响应 | 经过各种转换后的网络请求 |
| 是否看到重定向/重试 | 否(仅看到原始请求) | 是(能看到所有中间请求) |
| 是否看到缓存响应 | 是(可直接返回缓存) | 否(缓存响应不会到达此处) |
| 典型应用场景 | 日志记录、添加公共参数、请求加密 | 网络监控、响应压缩、调试网络问题 |
自定义拦截器示例
下面是一个简单的日志拦截器示例,用于记录请求和响应信息:
public class LoggingInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
// 记录请求信息
Request request = chain.request();
long t1 = System.nanoTime();
Logger.d(String.format("Sending request %s on %s%n%s",
request.url(), chain.connection(), request.headers()));
// 将请求传递给下一个拦截器并获取响应
Response response = chain.proceed(request);
// 记录响应信息
long t2 = System.nanoTime();
Logger.d(String.format("Received response for %s in %.1fms%n%s",
response.request().url(), (t2 - t1) / 1e6d, response.headers()));
return response;
}
}
使用方式:
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new LoggingInterceptor()) // 添加应用拦截器
.build();
拦截器的高级应用
-
添加公共参数:
Request newRequest = request.newBuilder() .addHeader("Authorization", "Bearer token") .build(); return chain.proceed(newRequest); -
请求重试机制:
for (int i = 0; i < maxRetries; i++) { try { return chain.proceed(request); } catch (IOException e) { if (i == maxRetries - 1) throw e; } } -
缓存策略:
Response response = chain.proceed(request); return response.newBuilder() .header("Cache-Control", "max-age=60") // 缓存1分钟 .build();
总结
拦截器是 OkHttp 最强大的特性之一,通过责任链模式实现了灵活的请求/响应处理机制。合理使用拦截器可以帮助你统一处理日志、认证、缓存、重试等横切关注点,提高代码复用性和可维护性。理解应用拦截器和网络拦截器的区别,并根据需求选择合适的拦截器类型,是使用好 OkHttp 的关键。

214

被折叠的 条评论
为什么被折叠?



