OkHttpClient实战指南:从基础请求到高级拦截器配置
1. OkHttpClient基础入门你的第一个HTTP请求OkHttpClient是Square公司开发的一款高效HTTP客户端库已经成为Android和Java开发者处理网络请求的首选工具。我第一次接触OkHttpClient是在2015年开发一个电商App时当时被它简洁的API设计和强大的功能所吸引。要创建一个最简单的GET请求你只需要几行代码OkHttpClient client new OkHttpClient(); Request request new Request.Builder() .url(https://api.example.com/data) .build(); Response response client.newCall(request).execute(); String responseData response.body().string();这段代码做了三件事创建了一个默认配置的OkHttpClient实例构建了一个指向目标URL的请求对象同步执行请求并获取响应数据在实际项目中我建议使用Builder模式来创建OkHttpClient实例这样后续扩展配置会更方便OkHttpClient client new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS) .writeTimeout(10, TimeUnit.SECONDS) .build();这里设置了三个关键的超时参数连接超时建立TCP连接的最长等待时间读取超时从服务器读取数据的最长等待时间写入超时向服务器发送数据的最长等待时间我曾经在一个物流追踪项目中遇到过超时设置不当的问题。当时设置的读取超时是5秒结果有些偏远地区的仓库服务器响应较慢导致频繁超时。后来调整为15秒后问题解决。这个经验告诉我超时设置需要根据实际业务场景灵活调整。2. 构建各种类型的HTTP请求2.1 GET请求与查询参数GET请求是最常用的请求类型OkHttpClient提供了多种添加查询参数的方式。我个人推荐使用HttpUrl.Builder它能自动处理URL编码问题HttpUrl url new HttpUrl.Builder() .scheme(https) .host(api.example.com) .addPathSegment(search) .addQueryParameter(q, android) .addQueryParameter(page, 1) .build(); Request request new Request.Builder() .url(url) .get() .build();2.2 POST请求与请求体对于需要发送数据的POST请求OkHttpClient支持多种媒体类型。最常见的是JSON格式MediaType JSON MediaType.get(application/json; charsetutf-8); String json {\username\:\test\,\password\:\123456\}; RequestBody body RequestBody.create(json, JSON); Request request new Request.Builder() .url(https://api.example.com/login) .post(body) .build();在处理文件上传时可以使用MultipartBodyRequestBody requestBody new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart(title, 测试图片) .addFormDataPart(image, avatar.jpg, RequestBody.create(new File(/sdcard/avatar.jpg), MediaType.parse(image/jpeg))) .build();2.3 处理响应数据获取到Response对象后我们需要正确处理响应数据。这里有几个注意事项一定要检查响应码response.isSuccessful()对于大文件响应应该使用流式处理而非一次性读取记得关闭响应体try (Response response client.newCall(request).execute()) { if (!response.isSuccessful()) { throw new IOException(Unexpected code response); } // 对于JSON响应 String jsonData response.body().string(); JSONObject json new JSONObject(jsonData); // 对于文件下载 InputStream inputStream response.body().byteStream(); // ...处理输入流 }3. 拦截器OkHttp的瑞士军刀3.1 基础拦截器实现拦截器是OkHttp最强大的功能之一。我把它比作HTTP请求的中间件可以在请求发出前和响应返回后插入自定义逻辑。创建一个基础拦截器很简单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, request.url())); Response response chain.proceed(request); long endTime System.nanoTime(); Log.d(OkHttp, String.format(Received response in %.1fms, (endTime - startTime) / 1e6d)); return response; } }使用这个拦截器OkHttpClient client new OkHttpClient.Builder() .addInterceptor(new LoggingInterceptor()) .build();3.2 网络拦截器与应用拦截器OkHttp有两种拦截器类型它们的区别很重要类型执行时机重定向处理调用次数应用拦截器最早执行不处理重定向可能多次网络拦截器较晚执行处理重定向通常一次网络拦截器的添加方式稍有不同OkHttpClient client new OkHttpClient.Builder() .addNetworkInterceptor(new LoggingInterceptor()) .build();3.3 实战认证拦截器下面展示一个实用的认证拦截器它会自动为特定请求添加Authorization头public class AuthInterceptor implements Interceptor { private String authToken; public AuthInterceptor(String token) { this.authToken token; } Override public Response intercept(Chain chain) throws IOException { Request original chain.request(); // 只为特定路径添加认证头 if (original.url().pathSegments().contains(secure)) { Request.Builder builder original.newBuilder() .header(Authorization, Bearer authToken); return chain.proceed(builder.build()); } return chain.proceed(original); } }4. 高级配置与性能优化4.1 连接池配置OkHttp默认使用连接池来复用HTTP连接这对性能有很大提升。我们可以自定义连接池参数ConnectionPool pool new ConnectionPool( 5, // 最大空闲连接数 5, // 保持时间(分钟) TimeUnit.MINUTES); OkHttpClient client new OkHttpClient.Builder() .connectionPool(pool) .build();4.2 缓存策略合理的缓存策略可以显著提升应用响应速度。OkHttp提供了完善的缓存机制Cache cache new Cache( new File(getCacheDir(), http_cache), 10 * 1024 * 1024); // 10MB缓存 OkHttpClient client new OkHttpClient.Builder() .cache(cache) .build();然后在请求中指定缓存策略Request request new Request.Builder() .url(url) .cacheControl(new CacheControl.Builder() .maxAge(1, TimeUnit.HOURS) // 1小时有效 .build()) .build();4.3 事件监听与统计OkHttp的EventListener可以监控请求的各个阶段非常适合性能分析class TimingListener extends EventListener { private long startNs; Override public void callStart(Call call) { startNs System.nanoTime(); } Override public void callEnd(Call call) { long elapsedMs (System.nanoTime() - startNs) / 1_000_000; Log.d(OkHttp, Call took elapsedMs ms); } } OkHttpClient client new OkHttpClient.Builder() .eventListener(new TimingListener()) .build();5. 常见问题排查与调试技巧5.1 使用HttpLoggingInterceptor添加依赖implementation com.squareup.okhttp3:logging-interceptor:4.9.0配置日志级别HttpLoggingInterceptor logging new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient client new OkHttpClient.Builder() .addInterceptor(logging) .build();5.2 处理SSL证书问题在开发环境中可能需要处理自签名证书CertificatePinner certificatePinner new CertificatePinner.Builder() .add(example.com, sha256/AAAAAAAAAAAAAAAAAAAAAAAA) .build(); OkHttpClient client new OkHttpClient.Builder() .certificatePinner(certificatePinner) .build();5.3 内存泄漏预防记得在适当的时候关闭响应体特别是在使用流式响应时try (Response response client.newCall(request).execute()) { // 使用response } catch (IOException e) { // 处理异常 }对于异步请求确保在Activity/Fragment销毁时取消请求private Call ongoingCall; // 发起请求 ongoingCall client.newCall(request); ongoingCall.enqueue(new Callback() { // 回调处理 }); // 在onDestroy中 if (ongoingCall ! null) { ongoingCall.cancel(); }在实际项目中我曾经遇到过一个内存泄漏问题在Fragment中发起异步请求但没有在onDestroyView中取消导致Fragment实例无法被回收。后来通过WeakReference和请求取消机制解决了这个问题。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2441869.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!