如何高效使用搜索引擎的使用Okhttp

使用OkHttp高效开发调试 - 简书
使用OkHttp高效开发调试
本文使用的OkHttp版本是okhttp3,使用okhttp2的情况稍有不同,使用okhttp2的同学替换为okhttp3也不麻烦,API都很接近;当然,如果想要使用okhttp2使用stetho & 拦截器也是可以的,可以参考官方文档。
先贴出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 sI
private OkHttpClient mOkHttpC
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)
public static OkHttpUtils getInstance() {
if (sInstance == null) {
synchronized (OkHttpUtils.class) {
if (sInstance == null) {
sInstance = new OkHttpUtils();
public OkHttpClient getOkHttpClient() {
return mOkHttpC
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中打开
看到如下界面,则代表监测成功,如果没有App显示,那应该就是忘了在Application中初始化Stetho
chrome://inspect/#devices.png
3.4 查看网络请求
HTTP响应body
3.5查看数据库
查看数据库
查看SharePreferences也同理,点击Local Storage就是你的App的所有SharePreferences。
4. 自定义OkHttp拦截器
当你与服务端对接的时候,当服务端功能还没开发完成,而你等待着服务器的接口测试时,自定义拦截器就可以帮你无需等待服务端完成功能先进行开发。步骤:1)先与服务端协商接口返回数据格式,拿到协商的数据,写一些假数据,每个接口对应建立一个JSON文本文件,里面放接口定义的数据。
数据文件,服务端同学提供测试数据.png
2)自定义拦截器
/** * 自定义okhttp拦截器,可定制接口伪造Http响应数据 */
public final class MockDataApiInterceptor implements Interceptor {
public static final String TAG = MockDataApiInterceptor.class.getSimpleName();
public Response intercept(Chain chain) throws IOException {
Response response =
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());
* 测试环境下拦截需要的接口请求,伪造数据返回
* @param chain 拦截器链
* @param path
请求的路径path
* @return 伪造的请求Response,有可能为null
private Response interceptRequestWhenDebug(Chain chain, String path) {
Response response =
if (BuildConfig.DEBUG) {
Request request = chain.request();
if (path.equalsIgnoreCase("/api/event")) {
//活动列表接口
response = getMockEventListResponse(request);
} else if (path.startsWith("/api/event/")) {
//活动详情接口
response = getMockEventDetailResponse(request);
* 伪造活动详情接口响应
* @param request 用户的请求
* @return 伪造的活动详情HTTP响应
private Response getMockEventDetailResponse(Request request) {
String data = MockDataGenerator.getMockDataFromJsonFile("mock/EventDetail.json");
response = getHttpSuccessResponse(request, data);
* 伪造活动列表接口响应
* @param request 用户的请求
* @return 伪造的活动列表HTTP响应
private Response getMockEventListResponse(Request request) {
String data = MockDataGenerator.getMockDataFromJsonFile("mock/EventList.json");
response = getHttpSuccessResponse(request, data);
* 根据数据JSON字符串构造HTTP响应,在JSON数据不为空的情况下返回200响应,否则返回500响应
* @param request
用户的请求
* @param dataJson 响应数据,JSON格式
* @return 构造的HTTP响应
private Response getHttpSuccessResponse(Request request, String dataJson) {
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,否则会抛出异常
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))
private Response getHttpFailedResponse(Chain chain, int errorCode, String errorMsg) {
if (errorCode & 0) {
throw new IllegalArgumentException("httpCode must not be negative");
response = new Response.Builder()
.code(errorCode)
.message(errorMsg)
.request(chain.request())
.protocol(Protocol.HTTP_1_0)
接口返回什么数据都由你自己定义,即使是Http的响应码等。这里的响应body我们使用服务端同学给我们提供的JSON文件
3)在build OkHttpClient时添加自定义拦截器
OkHttpClient.Builder().addInterceptor(new MockDataApiInterceptor())
4)进行开发,完善数据解析逻辑等,与View结合等。
5. OkHttp与Retrofit/RxJava组合请求
准备写一篇文章详细讲
Android DeveloperAndroid你必须学会的okhttp3_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
Android你必须学会的okhttp3
|0|0|文档简介
中国移动互联网行业领军品牌|
总评分0.0|
&&Android你必须学会的okhttp3
阅读已结束,如果下载本文需要使用2下载券
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩1页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢OkHttp 封装了请求和缓存和缓存
OkHttp是一个相对成熟的解决方案,据说Android4.4的源码中可以看到HttpURLConnection已经替换成OkHttp实现了。所以我们更有理由相信OkHttp的强大。
OkHttp 处理了很多网络疑难杂症:会从很多常用的连接问题中自动恢复。如果您的服务器配置了多个IP地址,当第一个IP连接失败的时候,OkHttp会自动尝试下一个IP。OkHttp还处理了代理服务器问题和SSL握手失败问题。
使用 OkHttp 无需重写您程序中的网络代码。OkHttp实现了几乎和HttpURLConnection一样的API。如果你用了&Apache&HttpClient,则OkHttp也提供了一个对应的okhttp-apache 模块。
OkHttp 和 fresco& retrofit 等第三方库能很好的衔接。
Okhttp作为HTTP引擎,retrofit作为restful业务架构实现;目前retrofit的restful风格规范是趋势。
OkHttp是一个高效的Http客户端
支持HTTP2/SPDY黑科技
socket自动选择最好路线,并支持自动重连
拥有自动维护的socket连接池,减少握手次数
拥有队列线程池,轻松写并发
拥有Interceptors轻松处理请求与响应(比如透明GZIP压缩,LOGGING)
基于Headers的缓存策略
注:什么是
SPDY(读作&SPeeDY&)是开发的基于的传输层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验。SPDY并不是一种用于替代HTTP的协议,而是对协议的增强。新协议的功能包括数据流的多路复用、请求优先级以及HTTP报头压缩。谷歌表示,引入SPDY协议后,在实验室测试中页面加载速度比原先快64%。中文名:spdy协议,目前SPDY已经被Http/2代替,google已经宣布要移除SPDY;
Connections: 对JDK中的socket进行了引用计数封装,用来控制socket连接
Streams: 维护HTTP的流,用来对Requset/Response进行IO操作
Calls: HTTP请求任务封装
StreamAllocation: 用来控制Connections/Streams的资源分配与释放
工作流程的概述
当我们用OkHttpClient.newCall(request)进行execute/enenqueue时,实际是将请求Call放到了Dispatcher中,okhttp使用进行线程分发,它有两种方法,一个是普通的同步单线程;另一种是使用了队列进行并发任务的分发(Dispatch)与回调,我们下面主要分析第二种,也就是队列这种情况,这也是okhttp能够竞争过其它库的核心功能之一;&
Socket管理(StreamAllocation)
经过上一步的分配,我们现在需要进行连接了。我们目前有封装好的Request,而进行HTTP连接需要进行Socket握手,Socket握手的前提是根据域名或代理确定Socket的ip与端口。这个环节主要讲了http的握手过程与连接池的管理,分析的对象主要是StreamAllocation。
Githug: &
配置方法:
注意:okhttp内部依赖okio,别忘了同时导入okio
(1)Android&Studio:
1 compile 'com.squareup.okhttp:okhttp:2.4.0'
导入okio:
1 compile 'com.squareup.okio:okio:1.5.0'
(2)Eclipse:
可以下载最新的jar&,添加依赖就可以用了
最新的jar地址:
1 //创建okHttpClient对象
2 OkHttpClient mOkHttpClient = new OkHttpClient();
3 // 创建Request.Builder
post请求方式
4 Request.Builder builder = new Request.Builder().post()
.url("/hongyangAndroid");
6 //创建一个Request
7 final Request request = builder.build();
8 //通过请求request,构造出call
9 Call call = mOkHttpClient.newCall(request);
(1)Request.Builder
通过Request.Builder设置更多的参数比如:
(1) 添加请求头header:
如果它本身存在值,在添加新的value之前,他们会被移除。使用addHeader(name, value)来添加头部不需要移除当前存在的headers。
1 builder.addHeader("SYSVERSION",
当写请求头,构造时用header(name, value)来为唯一出现的name设置value。
1 Request.Builder builder = new Request.Builder().post()
.url("/hongyangAndroid")
.header("Cookie", "OkHttpUser");
(2)添加method
请求携带参数:
post方式:
发布表单参数
1 String url =
2 // 创建builder
3 FormBody.Builder builder = new FormBody.Builder();
4 requestBody.add("user", "charles");
5 requestBody.add("age", "12");
6 // 创建RequestBody
7 RequestBody requestBody = builder.build();
9 Request request = new Request.Builder().post(requestBody ).url(url).build();
10 Response response = mOKHttpClient.newCall(request).execute();
发布multipart请求
MultipartBody.Builder可以构建与HTML文件上传表单兼容的复杂请求主体。例如文件上传
视频类:MediaType.parse("application/octet-stream")
1 File file = new File(Environment.getExternalStorageDirectory(), "about.jpg");
3 RequestBody fileBody = RequestBody.create(MediaType.parse("image/png"), file);
5 RequestBody requestBody = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addPart(Headers.of(
"Content-Disposition",
"form- name=\"username\""),
RequestBody.create(null, "charles"))
.addPart(Headers.of(
"Content-Disposition",
"form- name=\"imagefile\";
filename=\"aboutApp.jpg\""), fileBody)
17 Request request = new Request.Builder()
.url("http://.../fileUpload")
.post(requestBody)
22 Reponse reponse = mOkHttpClient.newCall(request).execute();
1 String url = url + "?" + "user=charles" + "&age=12"
2 Request request = new Request.Builder().get().url(url).build();
3 Response response = mOKHttpClient.newCall(request).execute();
执行call:
调用call.enqueue,将call加入调度队列,等待任务执行完成,在Callback中即可得到结果。
1 // 异步执行call
2 call.enqueue(new Callback()
public void onFailure(Request request, IOException e)
public void onResponse(final Response response) throws IOException
String htmlStr =
response.body().string();// 当前线程不是ui线程
(2)同步,阻塞方式:
1 Response response = call.execute();
Response:
(1)返回字符串,通过response.body().string()获取;
(2)返回二进制字节数组,通过response.body().bytes()获取;
(3)返回inputStream,通过response.body().byteStream()获取 (支持大文件下载);
阅读(...) 评论()

我要回帖

更多关于 如何高效使用mac 的文章

 

随机推荐