0x00 概述
OkHttp是一个轻量级的http网络请求开源框架,由Square公司开源,该公司也开源了其他项目,有兴趣的童鞋可以去Github-Square上去了解下其他相关开源项目。
OkHtttp是Android/Java应用的Http,HTTP/2客户端。使用OkHttp可以高效的发起HTTP请求,并节省带宽等资源,具体会在进阶篇中通过代码详解。
OkHttp由以下几方面优势,以至于Android系统已经将其集成作为HTTP框架使用。
- 允许对同一个主机的HTTP2请求共享一个socket链接
- 使用链接池来降低请求延迟
- 自动使用GZIP进行压缩
- 使用响应缓存来避免重复请求
除了以上官方所列出的之外,基本上支持各种需求。
0x10 引入
gradle
compile 'com.squareup.okhttp3:okhttp:3.8.1'
maven
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.8.1</version>
</dependency>
jar
下载jar包,地址:download okhttpjar
0x20 使用
OkHttp框架对整个请求的流程进行了抽象和封装,首先HTTP作为响应式应答,请求端抽象为客户端(OkHttpClient),然后每个请求抽象为一个Call,通过Request去构造一个Call,然后把call丢给OkHttp,根据Response做相应处理,就这么简单。
接下来看具体的请求类型:
0x21 Get
// 首先创建一个OkHttpClient来处理请求,可以通过Builder自定义Client.
OkHttpClient client = new OkHttpClient();
// 同步方式发起请求,并获取响应
String run(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
对,没错就这么简单,当然具体在业务中,肯定不是这样的使用方式,比如说:
/**
* 根据数据类型进行分装,统一处理
* @param url URL
* @return {@link APIResult}
*/
public static APIResult<JSONObject> doGet(String url) {
Request request = new Request.Builder().url(url).build();
try {
try (Response response = mInstance.newCall(request).execute()) {
if (response.isSuccessful()) {
String responseText = response.body().string();
Log.d(TAG, "doOkHttpRequest: response = " + responseText);
JSONObject jsonObject = new JSONObject(responseText);
return new APIResult<> (
OkHttpConstants.HTTP_REQUEST_RETURN_CODE_SUCCESS,
OkHttpConstants.HTTP_REQUESET_SUCCESS_ERROR_MESSAGE,
jsonObject);
}
} catch (JSONException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
在使用以上方式时,在Android中必须单独开启一个线程进行处理,OkHttp也提供了异步回调的方式,大大节省编码工作
/**
* 通过回调方式获取响应内容
* @param url URL
* @param responseCallback Response Callback
*/
public static void doGet(String url, Callback responseCallback) {
Request request = new Request.Builder().url(url).build();
mInstance.newCall(request).enqueue(responseCallback);
}
当然如果要近一步封装的话,可以对Callback进行一些封装和处理。
0x22 Post
public static final MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
和Get请求的区别就是,在构造Request时需要RequestBody丢进去,其他都是一样的,使用了Builder设计模式大大简化代码,也便于使用和理解。
其他请求方法就不过多介绍,有兴趣可以自己写下代码。
关于更多HTTP Method GO
0x30 总结
使用OkHttp三步走
- 创建OkHttpClient对象:new OkHttpClient()
- 创建Request对象:new Request.Builder().url(url).build()
- 处理Response:Response response = client.newCall(request).execute();
0x31 OkHttpClient
OkHttpClient:
请求工厂,用来发送HTTP请求,并读取响应。
OkHttpClient对象实例应该被共享
当使用单例创建OkHttpClient实例的时候并对所有的HTTP请求进行重用,OkHttpClient表现的最好。因为每个实例都拥有属于自己的链接池和线程池。重用这些链接和线程可以有效的减少延时和内存。相反,如果为每个请求创建一个实例会浪费那些在池中的资源。
使用默认构造器会创建一个默认设置的共享实例,或者使用Builder来创建一个自定义配置的共享实例。
如何构建一个自定义的OkHttpClient
通过自定义构建的共享OkHttpClient实例会共享同一个链接池,线程池,和配置,使用Builder方法配置用于特殊目的。
及时回收,当不需要处理的时候
OkHttpClient实例持有的链接和线程池,在空闲的时候会被自动释放。但是如果你的应用需要及时回收未使用的资源时,还是很有必要这么做的。
关闭调度器服务,这将引起未来实例的请求将被拒绝。
使用client.connectionPool().evictAll()清理链接池,注意,此时链接池的守护线程并不会马上退出。
如果你创建的实例中定义了缓存,调用client.cache().close(),需要注意的是,针对关闭的缓存创建调用是一个错误,这样做将导致调用崩溃。
OkHttp 也为http/2链接创建了守护线程,如果处于空闲状态将会自动退出。