使用OkHttp高效开发调试
2017-12-18 16:45
134 查看
本文使用的OkHttp版本是okhttp3,使用okhttp2的情况稍有不同,使用okhttp2的同学替换为okhttp3也不麻烦,API都很接近;当然,如果想要使用okhttp2使用stetho & 拦截器也是可以的,可以参考官方文档。
先贴出Gradle依赖,基本上我使用的都是最新版本的库。
OkHttp3拦截器Log打印.png在实例化你的HttpLoggingInterceptor的时候传入一个Logger参数,可以定制化OkHttp输出的格式化http请求体&响应体log。
chrome://inspect/#devices.png
步骤:
1)先与服务端协商接口返回数据格式,拿到协商的数据,写一些假数据,每个接口对应建立一个JSON文本文件,里面放接口定义的数据。
数据文件,服务端同学提供测试数据.png2)自定义拦截器
3)在build OkHttpClient时添加自定义拦截器
先贴出Gradle依赖,基本上我使用的都是最新版本的库。
def okhttp3Version = '3.4.1' compile('com.squareup.okhttp3:okhttp:' + okhttp3Version) compile('com.squareup.okhttp3:logging-interceptor:' + okhttp3Version) testCompile('com.squareup.okhttp3:mockwebserver:' + okhttp3Version) compile 'com.facebook.stetho:stetho-okhttp3:1.3.1'
1. 定义一个全局的OkHttp请求单例类,全局统一使用单一OkHttpClient:
/** * 全局统一使用的OkHttpClient工具,okhttp版本:okhttp3 */ public class OkHttpUtils { public static final long DEFAULT_READ_TIMEOUT_MILLIS = 15 * 1000; public static final long DEFAULT_WRITE_TIMEOUT_MILLIS = 20 * 1000; public static final long DEFAULT_CONNECT_TIMEOUT_MILLIS = 20 * 1000; private static final long HTTP_RESPONSE_DISK_CACHE_MAX_SIZE = 10 * 1024 * 1024; private static volatile OkHttpUtils sInstance; private OkHttpClient mOkHttpClient; private OkHttpUtils() { HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); //包含header、body数据 loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); mOkHttpClient = new OkHttpClient.Builder() .readTimeout(DEFAULT_READ_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS) .writeTimeout(DEFAULT_WRITE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS) .connectTimeout(DEFAULT_CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS) //FaceBook 网络调试器,可在Chrome调试网络请求,查看SharePreferences,数据库等 .addNetworkInterceptor(new StethoInterceptor()) //http数据log,日志中打印出HTTP请求&响应数据 .addInterceptor(loggingInterceptor) .build(); } public static OkHttpUtils getInstance() { if (sInstance == null) { synchronized (OkHttpUtils.class) { if (sInstance == null) { sInstance = new OkHttpUtils(); } } } return sInstance; } public OkHttpClient getOkHttpClient() { return mOkHttpClient; } public void setCache(Context appContext) { final File baseDir = appContext.getApplicationContext().getCacheDir(); if (baseDir != null) { final File cacheDir = new File(baseDir, "HttpResponseCache"); mOkHttpClient.newBuilder().cache((new Cache(cacheDir, HTTP_RESPONSE_DISK_CACHE_MAX_SIZE))); } } }在所有需要用到OkHttpClient的地方使用以下代码,全局使用同一个OkHttpClient实例:
OkHttpClient okHttpClient = OkHttpUtils.getInstance().getOkHttpClient();全局使用一个OkHttpClient的原因是所有请求没必要创建多个请求客户端实例,一个好处是节省内存,另外一个是全局设定了一些监控工具,如Facebook的Stetho 和 OkHttp自带的HttpLoggingInterceptor,你就可以监管你的所有Http请求。
2. HttpLoggingInterceptor Log直接观察HTTP请求&响应数据
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); //包含header、body数据 loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); //在build OkHttpClient的时候加入Log拦截器 OkHttpClient.Builder().addInterceptor(loggingInterceptor)
HttpLoggingInterceptor的效果如下图,开发时如果需要看整个App的所有请求及相应,可以使用okhttp关键字过滤。
OkHttp3拦截器Log打印.png在实例化你的HttpLoggingInterceptor的时候传入一个Logger参数,可以定制化OkHttp输出的格式化http请求体&响应体log。
3. Facebook强大的监测工具:Stetho
3.1 在build OkHttpClient时需要添加网络拦截器
OkHttpClient.Builder().addNetworkInterceptor(new StethoInterceptor())
3.2 在Application的OnCreate中初始化
//FaceBook调试器,可在Chrome调试网络请求,查看SharePreferences,数据库等 Stetho.initializeWithDefaults(this);
3.3 连接手机,在Chrome中打开<a>chome://inspect/#devices</a>
看到如下界面,则代表监测成功,如果没有App显示,那应该就是忘了在Application中初始化Stetho
chrome://inspect/#devices.png
3.4 查看网络请求
请求概览HTTP响应body3.5查看数据库
查看数据库查看SharePreferences也同理,点击Local Storage就是你的App的所有SharePreferences。4. 自定义OkHttp拦截器
当你与服务端对接的时候,当服务端功能还没开发完成,而你等待着服务器的接口测试时,自定义拦截器就可以帮你无需等待服务端完成功能先进行开发。步骤:
1)先与服务端协商接口返回数据格式,拿到协商的数据,写一些假数据,每个接口对应建立一个JSON文本文件,里面放接口定义的数据。
数据文件,服务端同学提供测试数据.png2)自定义拦截器
/** * 自定义okhttp拦截器,可定制接口伪造Http响应数据 */ public final class MockDataApiInterceptor implements Interceptor { public static final String TAG = MockDataApiInterceptor.class.getSimpleName(); @Override public Response intercept(Chain chain) throws IOException { Response response = null; String path = chain.request().url().uri().getPath(); LogUtil.d(TAG, "intercept: path=" + path); response = interceptRequestWhenDebug(chain, path); if (null == response) { LogUtil.i(TAG, "intercept: null == response"); response = chain.proceed(chain.request()); } return response; } /** * 测试环境下拦截需要的接口请求,伪造数据返回 * * @param chain 拦截器链 * @param path 请求的路径path * @return 伪造的请求Response,有可能为null */ private Response interceptRequestWhenDebug(Chain chain, String path) { Response response = null; if (BuildConfig.DEBUG) { Request request = chain.request(); if (path.equalsIgnoreCase("/api/event")) { //活动列表接口 response = getMockEventListResponse(request); } else if (path.startsWith("/api/event/")) { //活动详情接口 response = getMockEventDetailResponse(request); } } return response; } /** * 伪造活动详情接口响应 * * @param request 用户的请求 * @return 伪造的活动详情HTTP响应 */ private Response getMockEventDetailResponse(Request request) { Response response; String data = MockDataGenerator.getMockDataFromJsonFile("mock/EventDetail.json"); response = getHttpSuccessResponse(request, data); return response; } /** * 伪造活动列表接口响应 * * @param request 用户的请求 * @return 伪造的活动列表HTTP响应 */ private Response getMockEventListResponse(Request request) { Response response; String data = MockDataGenerator.getMockDataFromJsonFile("mock/EventList.json"); response = getHttpSuccessResponse(request, data); return response; } /** * 根据数据JSON字符串构造HTTP响应,在JSON数据不为空的情况下返回200响应,否则返回500响应 * * @param request 用户的请求 * @param dataJson 响应数据,JSON格式 * @return 构造的HTTP响应 */ private Response getHttpSuccessResponse(Request request, String dataJson) { Response response; if (TextUtils.isEmpty(dataJson)) { LogUtil.w(TAG, "getHttpSuccessResponse: dataJson is empty!"); response = new Response.Builder() .code(500) .protocol(Protocol.HTTP_1_0) .request(request) //必须设置protocol&request,否则会抛出异常 .build(); } else { response = new Response.Builder() .code(200) .message(dataJson) .request(request) .protocol(Protocol.HTTP_1_0) .addHeader("Content-Type", "application/json") .body(ResponseBody.create(MediaType.parse("application/json"), dataJson)) .build(); } return response; } private Response getHttpFailedResponse(Chain chain, int errorCode, String errorMsg) { if (errorCode < 0) { throw new IllegalArgumentException("httpCode must not be negative"); } Response response; response = new Response.Builder() .code(errorCode) .message(errorMsg) .request(chain.request()) .protocol(Protocol.HTTP_1_0) .build(); return response; } }接口返回什么数据都由你自己定义,即使是Http的响应码等。这里的响应body我们使用服务端同学给我们提供的JSON文件
3)在build OkHttpClient时添加自定义拦截器
OkHttpClient.Builder().addInterceptor(new MockDataApiInterceptor())4)进行开发,完善数据解析逻辑等,与View结合等。
相关文章推荐
- 使用VS2005搭建典型高效的SharePoint开发环境,提高生产效率,包含远程调试,自动部署
- 使用VisualStudio高效开发调试AndroidNDK
- 详解如何使用VisualStudio高效开发调试AndroidNDK
- 使用VS2005搭建典型高效的SharePoint开发环境,提高生产效率,包含远程调试,自动部署
- 使用VS2005搭建典型高效的SharePoint开发环境,提高生产效率,包含远程调试,自动部署
- Android—App—必备开发组件—调试工具篇—Stetho[配合OkHttp框架使用]
- 如何使用PHP开发高效的WEB系统 推荐
- 如何使用PHP开发高效的WEB系统
- IE8"开发人员工具"使用详解下(浏览器模式、文本模式、JavaScript调试、探查器)
- 第11章 库的开发、调试和使用
- 使用科学高效的软件开发过程
- WinForm控件开发总结(二)------使用和调试自定义控件
- 使用VS2005开发 mobile无法调试的解决方法
- IE8"开发人员工具"使用详解下(浏览器模式、文本模式、JavaScript调试、探查器)
- 使用Visual Studio 2010开发和调试Html5项目
- 使用Visual Studio 2010开发和调试Html5项目
- iPhone软件开发之iDP使用,以及真机调试
- 解答:如何使用PHP开发高效的WEB系统
- 如何使用PHP开发高效的WEB系统
- 使用VIM开发软件项目 - (15) 在VIM中使用GDB调试 (一)