OkHttp 官网
官网地址 : http://square.github.io/okhttp
GitHub地址: https://github.com/square/okhttp
1 基础介绍
OkHttp 是一款优秀的开源 HTTP 框架 , 支持Android 2.3 及其以上版本 , 主要功能如下 :
- GET 请求
- POST 请求
- 基于 HTTP 的文件 上传和下载
- 图片加载
- 下载文件的 GZIP 压缩 节省带宽
- 响应缓存 避免重复的网络请求
- 使用连接池来降低响应延迟问题
2 使用准备
Android Studio 使用方式
在项目 Module 的 build.gradle 文件中增加如下代码,然后 Sync project 成功后即可使用.
compile 'com.squareup.okhttp3:okhttp:3.5.0'
注意增加网络访问权限在AndroidManifest.xml文件中
<uses-permission android:name="android.permission.INTERNET"/>
3 基本使用
3.1 GET 请求
/**
* OkHttp Get请求测试方法.
* @param url URL 地址.
* @return
* 返回数据.
* @throws IOException
*/
public String okHttp_get(String url)throws IOException{
// 1. 创建HTTP Client 对象.尽量使用全局的避免过多创建该对象
OkHttpClient client = new OkHttpClient();
// 2. 创建请求对象 .
Request request = new Request.Builder()
.url(url)
.build();
// 3. 执行请求,获取请求响应对象.
Response response = client.newCall(request).execute();
// 4. 处理结果
if (response.isSuccessful()){
// 请求成功
Log.d(TAG,"请求成功.");
return response.body().string();
}else {
Log.e(TAG,"请求失败!");
return null;
}
}
3.2 POST 请求
// 数据类型.
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
/**
* OkHttp POST 请求.
* @param url URL地址
* @param json JSON 格式数据
* @return
* 响应数据
* @throws IOException
*/
public String OkHttp_post(String url,String json)throws IOException{
// 1. 创建Client对象
OkHttpClient client = new OkHttpClient();
// 2. 创建POST请求体
RequestBody requestBody = RequestBody.create(JSON,json);
// 3. 创建 请求对象.
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
// 4. 发送请求 , 创建响应对象
Response response = client.newCall(request).execute();
// 5. 处理结果
if (response.isSuccessful()){
// 成功
Log.d(TAG,"请求成功.");
return response.body().string();
}else {
// 失败
Log.e(TAG,"请求失败!");
return null;
}
}
3.3 带键值对的POST
/**
* 带键值的 POST请求
* @param url URL地址
* @return
* 响应数据字符串.
* @throws IOException
*/
public String OkHttp_post_key(String url)throws IOException{
// 1. 创建对象.
OkHttpClient client = new OkHttpClient();
// 2. 创建请求体.
FormBody.Builder builder = new FormBody.Builder();
builder.add("name","WSJ")
.add("sex","male")
.add("age","22");
FormBody formBody = builder.build();
Request request = new Request.Builder()
.url(url)
.post(formBody)
.build();
// 3. 发送请求.
Response response = client.newCall(request).execute();
// 4. 处理响应
if (response.isSuccessful()){
Log.d(TAG,"请求成功.");
return response.body().string();
}else {
Log.e(TAG,"请求失败!");
return response.body().string();
}
}
4 OkHttp 相关类介绍.
4.1 OkHttpClient 类
请求工厂类, 它可以用来发送 HTTP 请求, 读取请求响应.
使用 OkHttpClient 类时应该公用一个实例对象, 因为每一个 OkHttpClient 实例对象保持着他们自己的连接池和线程池,重用连接和线程将会节省电量和内存,因此如果为每一次网络请求都创建一个OkHttpClient对象就会造成资源浪费
(1) 创建OkHttpClient对象的两种方式
方式一 :使用默认配置 new OkHttpClient()
// 创建一个单例 客户端 .
public final OkHttpClient client = new OkHttpClient();
方式二 :自定义配置 new OkHttpClient.Builder()
// The singleton HTTP client.
public final OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new HttpLoggingInterceptor())
.cache(new Cache(cacheDir, cacheSize))
.build();
使用 newBuilder()
可以自定义一个OkHttpClient实例对象. 创建出来的client同样是共享连接池和线程池以及配置信息.可以使用 builder
的相关方法创建出指定功能的client对象.
// 500ms超时.
OkHttpClient eagerClient = client.newBuilder()
.readTimeout(500, TimeUnit.MILLISECONDS)
.build();
Response response = eagerClient.newCall(request).execute();
(2) 资源释放问题
当 OkHttpClient 所保持的连接处于空闲状态时, OkHttpClient 会自动将这些连接占用的资源释放掉. 因此不需要我们主动去释放.如果想在程序中主动强制释放这些资源,可以进行如下操作 :
第一步 : shutdown()
方法将 dispatcher's executor
服务关闭.
// 关闭服务.
client.dispatcher().executorService().shutdown();
第二步 : evictAll()
清空连接池,
注意 : 连接池的守护线程不会立即退出.
// 清空连接池
client.connectionPool().evictAll();
第三步 : close()
关闭缓存(如果有).
注意 :如果关闭了缓存则不能创建 Call 否则会出错.
// 关闭缓存
client.cache().close();
(3) 常用方法
// 创建新的 Call 对象, 准备发送请求.
public Call newCall(Request request);
4.2 Request 类
HTTP 请求类,如果该类的 body
是null 或者他本身是不可变的那么该实例对象是不可变的.
(1) 内部类 Request.Builder
该类可以用来创建 Request 对象. 就像组装机器一样构造一个实例对象.
// 构造方法
public Builder();
// 设置目标 URL 方法
public Request.Builder url(HttpUrl url);
public Request.Builder url(String url);
public Request.Builder url(URL url);
// 设置/修改 HTTP 请求头信息
public Request.Builder header(String name,String value);
// 增加一个请求头.Prefer this method for multiply-valued headers like "Cookie".
public Request.Builder addHeader(String name,String value);
// 删除请求头指定信息
public Request.Builder removeHeader(String name);
// 使用参数中的请求头信息替换原来的请求头.
public Request.Builder headers(Headers headers);
// 设置缓存策略
public Request.Builder cacheControl(CacheControl cacheControl);
// get 请求
public Request.Builder get();
// head 请求
public Request.Builder head();
// POST 请求
public Request.Builder post(RequestBody body);
// delete 请求
public Request.Builder delete(RequestBody body);
public Request.Builder delete();
// 设置请求
public Request.Builder method(String method,RequestBody body);
// 设置 请求 TAG,可以在取消请求时使用.如果TAG为空或者未设置,则他本事就是TAG.
public Request.Builder tag(Object tag);
(1) 其他方法
// 获取请求体数据对象.
public RequestBody body();
// Builder对象.
public Request.Builder newBuilder();
// 缓存策略.
public CacheControl cacheControl();
// 是否是 HTTPS
public boolean isHttps();
// 获取制定文件头信息.
public String header(String name);
// 获取请求头
public Headers headers();
public List<String> headers(String name);
// 请求方法
public String method();
// URL 地址.
public HttpUrl url();
4.3 RequestBody 类
请求体类.
// 构造方法.
public RequestBody();
// 返回将要发送的数据,如果不知道就返回 -1;
public long contentLength() throws IOException;
// 返回一个新的请求数据体对象,如果 `contentType` 非空,并且未指定编码格式则默认为 `UTF-8`
public static RequestBody create(MediaType contentType,String content);
public static RequestBody create(MediaType contentType,okio.ByteString content);
public static RequestBody create(MediaType contentType,byte[] content);
// 分段上传.
public static RequestBody create(MediaType contentType,
byte[] content,
int offset,
int byteCount);
// 可以实现文件上传
public static RequestBody create(MediaType contentType,File file);
4.4 Response 类
请求响应对象. 使用完成后需要关闭.
// 获取响应数据 , 使用之后必须关闭
public ResponseBody body();
// HTTP 请求响应代码
public int code();
// Returns true if the code is in [200..300),
// which means the request was successfully received, understood, and accepted.
public boolean isSuccessful();
// HTTP 状态信息
public String message();
4.5 ResponseBody 类
响应数据对象. 使用后一定要 关闭 .
Response
和 ResponseBody
类都需要关闭.如果关闭了 Response
则就会默认关闭它的ResponseBody
.
关闭阻塞式
Call call = client.newCall(request);
try (Response response = call.execute()) {
... // Use the response.
}
关闭异步请求
Call call = client.newCall(request);
call.enqueue(new Callback() {
public void onResponse(Call call, Response response) throws IOException {
try (ResponseBody responseBody = response.body()) {
... // Use the response.
}
}
public void onFailure(Call call, IOException e) {
... // Handle the failure.
}
});