主要对象和概念
1. OkHttpClient
HTTP 请求的入口点,建议作为单例使用(线程安全且资源高效)
// 创建默认配置的客户端
OkHttpClient client = new OkHttpClient();
// 自定义配置的客户端
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.cache(new Cache(cacheDirectory, cacheSize))
.addInterceptor(new LoggingInterceptor())
.addNetworkInterceptor(new StethoInterceptor())
.build();2. Request
表示 HTTP 请求,包含 URL、方法、头部和请求体
// GET 请求
Request request = new Request.Builder()
.url("https://api.example.com/data")
.header("Authorization", "Bearer token123")
.build();
// POST 请求(带 JSON 数据)
MediaType JSON = MediaType.get("application/json; charset=utf-8");
String json = "{\"name\":\"John\", \"age\":30}";
RequestBody body = RequestBody.create(json, JSON);
Request request = new Request.Builder()
.url("https://api.example.com/users")
.post(body)
.build();3. Call
表示一个准备执行的请求,可以同步或异步执行
// 同步请求
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
String responseData = response.body().string();
// 处理响应
}
}
// 异步请求
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 responseData = response.body().string();
// 处理响应(注意:不在主线程)
}
}
});4. Response
表示 HTTP 响应,包含状态码、头部和响应体
try (Response response = client.newCall(request).execute()) {
// 状态信息
int statusCode = response.code();
String message = response.message();
// 头部信息
String contentType = response.header("Content-Type");
Headers headers = response.headers();
// 响应体
ResponseBody body = response.body();
String stringBody = body.string(); // 只能调用一次
byte[] bytes = body.bytes(); // 只能调用一次
InputStream stream = body.byteStream(); // 可多次读取
}<!> 注意 确保在使用后关闭 Response 以避免资源泄漏
5. Interceptor
拦截器,用于在请求发送前和响应接收后添加自定义逻辑
// 日志拦截器
public class LoggingInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
long startTime = System.nanoTime();
Log.d("OkHttp", String.format("Sending request %s on %s%n%s",
request.url(), chain.connection(), request.headers()));
Response response = chain.proceed(request);
long endTime = System.nanoTime();
Log.d("OkHttp", String.format("Received response for %s in %.1fms%n%s",
response.request().url(), (endTime - startTime) / 1e6d, response.headers()));
return response;
}
}常用功能
1. 表单提交
RequestBody formBody = new FormBody.Builder()
.add("username", "john")
.add("password", "secret")
.build();
Request request = new Request.Builder()
.url("https://api.example.com/login")
.post(formBody)
.build();2. 文件上传
MediaType mediaType = MediaType.parse("image/jpeg");
File file = new File("path/to/image.jpg");
RequestBody requestBody = RequestBody.create(file, mediaType);
Request request = new Request.Builder()
.url("https://api.example.com/upload")
.post(requestBody)
.build();3. 多部分请求 Multipart
MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("title", "My Image")
.addFormDataPart("image", "image.png", RequestBody.create(new File("path/to/image.png"), MEDIA_TYPE_PNG))
.build();
Request request = new Request.Builder()
.url("https://api.example.com/upload")
.post(requestBody)
.build();4. 超时设置
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS) // 连接超时
.readTimeout(30, TimeUnit.SECONDS) // 读取超时
.writeTimeout(30, TimeUnit.SECONDS) // 写入超时
.callTimeout(60, TimeUnit.SECONDS) // 整个调用超时
.build();5. 缓存配置
// 设置缓存(10MB)
int cacheSize = 10 * 1024 * 1024; // 10 MB
File cacheDirectory = new File(context.getCacheDir(), "http-cache");
Cache cache = new Cache(cacheDirectory, cacheSize);
OkHttpClient client = new OkHttpClient.Builder()
.cache(cache)
.build();6. Cookie 管理
// 使用持久化 CookieJar
CookieJar cookieJar = new PersistentCookieJar(
new SetCookieCache(),
new SharedPrefsCookiePersistor(context)
);
OkHttpClient client = new OkHttpClient.Builder()
.cookieJar(cookieJar)
.build();高级特性
1. 连接池管理
ConnectionPool connectionPool = new ConnectionPool(5, 5, TimeUnit.MINUTES);
OkHttpClient client = new OkHttpClient.Builder()
.connectionPool(connectionPool)
.build();2. 证书 pinning
// 只信任指定证书
String hostname = "publicobject.com";
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add(hostname, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.build();
OkHttpClient client = new OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build();3. 代理设置
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.example.com", 8080));
OkHttpClient client = new OkHttpClient.Builder()
.proxy(proxy)
.build();4. 认证
// 基本认证
Authenticator authenticator = new Authenticator() {
@Override
public Request authenticate(Route route, Response response) throws IOException {
String credential = Credentials.basic("username", "password");
return response.request().newBuilder()
.header("Authorization", credential)
.build();
}
};
OkHttpClient client = new OkHttpClient.Builder()
.authenticator(authenticator)
.build();错误处理
1. 网络错误
try {
Response response = client.newCall(request).execute();
// 处理响应
} catch (IOException e) {
// 网络连接问题
if (e instanceof SocketTimeoutException) {
// 超时错误
} else if (e instanceof UnknownHostException) {
// DNS解析错误
} else {
// 其他网络错误
}
}2. HTTP 状态码错误
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) {
switch (response.code()) {
case 400:
// 错误请求
break;
case 401:
// 未授权
break;
case 404:
// 未找到
break;
case 500:
// 服务器错误
break;
default:
// 其他HTTP错误
}
}