一、OkHttp 简介
OkHttp 是 Square 公司开发的一个高效的 HTTP 客户端,它具有以下特点:
-
支持 HTTP/2,允许对同一主机的所有请求共享一个套接字
-
连接池减少了请求延迟(如果 HTTP/2 不可用)
-
透明的 GZIP 压缩减少了下载大小
-
响应缓存完全避免了重复请求的网络传输
二、OkHttp 工作流程图
三、OkHttp 核心组件
1. OkHttpClient
OkHttpClient 是 OkHttp 的核心类,负责协调各个组件的工作。通常建议将其设计为单例模式。
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.cache(new Cache(cacheDirectory, cacheSize))
.build();
2. Request 和 Response
-
Request:封装了 HTTP 请求的所有信息(URL、方法、头、体等)
-
Response:封装了 HTTP 响应的所有信息(状态码、头、体等)
3. Call
Call 代表一个已准备好执行的请求,它提供了同步和异步两种执行方式。
四、OkHttp 工作流程详解
1. 同步请求流程
Request request = new Request.Builder()
.url("https://api.example.com/data")
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
// 处理响应
String responseData = response.body().string();
System.out.println(responseData);
}
2. 异步请求流程
Request request = new Request.Builder()
.url("https://api.example.com/data")
.build();
client.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 {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
// 处理响应
String responseData = response.body().string();
System.out.println(responseData);
}
});
五、OkHttp 拦截器机制
OkHttp 的强大之处在于其拦截器机制,它允许我们在请求和响应的处理过程中插入自定义逻辑。
1. 内置拦截器
-
RetryAndFollowUpInterceptor:负责重试和重定向
-
BridgeInterceptor:桥接应用代码和网络代码
-
CacheInterceptor:处理缓存
-
ConnectInterceptor:建立到目标服务器的连接
-
CallServerInterceptor:向服务器发送请求并读取响应
2. 自定义拦截器示例
class LoggingInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
long t1 = System.nanoTime();
System.out.println(String.format("Sending request %s on %s%n%s",
request.url(), chain.connection(), request.headers()));
Response response = chain.proceed(request);
long t2 = System.nanoTime();
System.out.println(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();
六、OkHttp 高级特性
1. 连接池管理
OkHttp 自动管理连接池,复用 TCP 连接以减少延迟。
2. 缓存控制
int cacheSize = 10 * 1024 * 1024; // 10 MiB
Cache cache = new Cache(getCacheDir(), cacheSize);
OkHttpClient client = new OkHttpClient.Builder()
.cache(cache)
.build();
3. Cookie 管理
CookieJar cookieJar = new CookieJar() {
private final HashMap<HttpUrl, List<Cookie>> cookieStore = new HashMap<>();
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
cookieStore.put(url, cookies);
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
List<Cookie> cookies = cookieStore.get(url);
return cookies != null ? cookies : new ArrayList<Cookie>();
}
};
OkHttpClient client = new OkHttpClient.Builder()
.cookieJar(cookieJar)
.build();
七、性能优化建议
-
使用单例 OkHttpClient:避免重复创建客户端实例
-
合理设置超时时间:根据网络状况调整
-
启用响应缓存:减少重复请求
-
使用连接池:默认已启用,无需额外配置
-
合理使用拦截器:避免在拦截器中执行耗时操作
八、常见问题解决
-
HTTPS 证书问题:自定义信任管理器处理自签名证书
-
网络权限问题:确保 AndroidManifest.xml 中声明了网络权限
-
主线程网络请求:避免在主线程执行同步请求
-
响应体关闭:确保及时关闭 ResponseBody 防止内存泄漏
九、总结
OkHttp 作为 Android 平台上最流行的网络请求库之一,其设计精良、功能强大且易于扩展。通过理解其工作原理和拦截器机制,我们可以更好地利用它来满足各种复杂的网络请求需求,同时也能针对特定场景进行优化和定制。
希望本文能帮助你全面理解 OkHttp 的工作机制,并在实际开发中灵活运用。