Okhttp 全面剖析来啦(一)

3,987 阅读4分钟

关于Okhttp(一)

简介

Okhttp是square公司推出的一款Android和Java网络请求库,当前推出了Okhttp3,在原来的基础上做了很大改进,也是Android目前最流行的网络库之一,本系列文章就是基于最新的来剖析。鉴于能力以及代码的优化改动,文中如有不足之处还望指教,谢谢。

特点

  1. Http/2支持多路复用
  2. 采用连接池减少请求延时
  3. 支持GZIP压缩
  4. 响应缓存
  5. 支持websocket
  6. 多ip切换(连接失败并且服务器有多ip)

基本使用

Android使用注意申请网络权限,同时不能在主线程请求

设置缓存

设置缓存超级简单,只需在创建OkHttpClitent时定义缓存目录即可,同时它是基于http的方式来处理缓存,后面会详细解释

OkHttpClient okHttpClient = new OkHttpClient.Builder()
// 大小是bytes
.cache(new Cache(new File("xx/xxx/"), 20 * 1024))
.build();

Okhttp仅支持get请求缓存哦,其他请求方式需要自己实现

超时设置

okhttp超时分为连接超时、读取超时、写入超时

OkHttpClient okHttpClient = new OkHttpClient.Builder()
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.connectTimeout(10, TimeUnit.SECONDS)
.pingInterval(10, TimeUnit.SECONDS) // websocket 轮训间隔
.build();

Cookie保存

Cookie的保存也提供了快捷方式,当然也可以通过拦截器自己实现

OkHttpClient okHttpClient = new OkHttpClient.Builder()
.cookieJar(new CookieJar() {
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
// 保存cookie通常使用SharedPreferences
}

@Override
public List<Cookie> loadForRequest(HttpUrl url) {
// 从保存位置读取,注意此处不能为空,否则会导致空指针
return new ArrayList<>();
}
})
.build();

添加拦截器

okhttp3的实现使用的是链式的拦截器,同时也开放了自定义拦截器接口

OkHttpClient okHttpClient = new OkHttpClient.Builder()
// 此种拦截器将会在请求开始的时候调用
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
// 略
return null;
}
})
// 连接成功,读写数据前调用
.addNetworkInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
// 略
return null;
}
})
.build();

Https

okhttp3完全支持https,只要设置好证书即可

OkHttpClient okHttpClient = new OkHttpClient.Builder()
// 创建一个证书工厂
.sslSocketFactory(SSLSocketFactory, X509TrustManager)
.build();

GET

// 1.创建一个OkHttpClient,通常是单例,如果要自定义一些属性那就要用内部的Builder来构造
/**
* OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor() //请求前的拦截器
.addNetworkInterceptor() // 网络拦截器
.cache() // 缓存目录
.connectTimeout() // 连接超时
.cookieJar() // cookie的读取,保存,需要自己实现
.sslSocketFactory() // https证书
...略...
.build();
*/
OkHttpClient client = new OkHttpClient();

String run(String url) throws IOException {
// 2. 创建一个request,包含请求地址、请求参数、请求头等
Request request = new Request.Builder()
.url(url)
.build();

// 3. 同步请求,得到响应
Response response = client.newCall(request).execute();
return response.body().string();
}

POST

// 1.创建OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.build();

// 2.创建请求参数,注意,此处有多种方式
RequestBody requestBody = new FormBody.Builder()
.add("param", "value")
.build();
// 3.创建请求request
Request request = new Request.Builder()
.url("https://wwww.xxx.com")
.post(requestBody)
.build();
// 4.发起请求,此处使用的是异步请求,按需要选择同步或异步
okHttpClient.newCall(request)
.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {

}

@Override
public void onResponse(Call call, Response response) throws IOException {
// 5.处理相响应
}
});

上传文件

上传文件本质上是post请求,区别是在参数类型上

不要忘记权限,6.0(api23)动态权限

// 1.创建OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.build();

// 不同点
// 2.创建请求参数,设置对应的参数类型即可
RequestBody requestBody = RequestBody.create(MediaType.parse("text/x-markdown; charset=utf-8"), new File("xxx.txt"));
// 3.创建请求request
Request request = new Request.Builder()
.url("https://wwww.xxx.com")
.post(requestBody)
.build();
// 4.发起请求
okHttpClient.newCall(request)
.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {

}

@Override
public void onResponse(Call call, Response response) throws IOException {
// 5.处理相响应
}
});

Multipart文件

multipart文件同上传文件,区别是它可以同时有字符参数,也可以有文件

// 1.创建OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.build();

// 不同点
// 2.创建请求参数,设置对应的参数类型即可
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("fileParam", "xxx.png", RequestBody.create(MediaType.parse("image/png"), new File("xxx/xxx.png")))
.addFormDataPart("param", "value")
.build();
// 3.创建请求request
Request request = new Request.Builder()
.url("https://wwww.xxx.com")
.post(requestBody)
.build();
// 4.发起请求
okHttpClient.newCall(request)
.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {

}

@Override
public void onResponse(Call call, Response response) throws IOException {
// 5.处理相响应
}
});

Websocket

okhttp3支持websocket,如果不了解请自行搜索,简易推送,轮训都可以使用。

websocket协议首先会发起http请求,握手成功后,转换协议保持长连接,类似心跳

// 方法可以选择实现
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.build();
Request request = new Request.Builder()
.url("https://wwww.xxx.com")
.build();
okHttpClient.newWebSocket(request, new WebSocketListener() {
@Override
public void onMessage(WebSocket webSocket, String text) {
super.onMessage(webSocket, text);
// 当收到文本消息
}

@Override
public void onOpen(WebSocket webSocket, Response response) {
super.onOpen(webSocket, response);
// 连接成功
}

@Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
super.onMessage(webSocket, bytes);
// 收到字节消息,可转换为文本
}

@Override
public void onClosed(WebSocket webSocket, int code, String reason) {
super.onClosed(webSocket, code, reason);
// 连接被关闭
}

@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
super.onFailure(webSocket, t, response);
// 连接失败
}
});

总结

Okhttp3已经成为android必备的网络请求库,同时也是比较好用的库,对于更多Okhttp的实现细节,请看下节

坚持原创技术分享,您的支持将鼓励我继续创作! 赏 lowett WeChat Pay

微信打赏