簡(jiǎn)介
Okhttp是square公司推出的一款A(yù)ndroid和Java網(wǎng)絡(luò)請(qǐng)求庫(kù),當(dāng)前推出了Okhttp3,在原來的基礎(chǔ)上做了很大改進(jìn),也是Android目前最流行的網(wǎng)絡(luò)庫(kù)之一,本系列文章就是基于最新的來剖析。鑒于能力以及代碼的優(yōu)化改動(dòng),文中如有不足之處還望指教,謝謝。
特點(diǎn)
- Http/2支持多路復(fù)用
- 采用連接池減少請(qǐng)求延時(shí)
- 支持GZIP壓縮
- 響應(yīng)緩存
- 支持websocket
- 多ip切換(連接失敗并且服務(wù)器有多ip)
基本使用
Android使用注意申請(qǐng)網(wǎng)絡(luò)權(quán)限,同時(shí)不能在主線程請(qǐng)求
<uses-permission android:name="android.permission.INTERNET"/>
設(shè)置緩存
設(shè)置緩存超級(jí)簡(jiǎn)單,只需在創(chuàng)建OkHttpClitent時(shí)定義緩存目錄即可,同時(shí)它是基于http的方式來處理緩存,后面會(huì)詳細(xì)解釋
OkHttpClient okHttpClient = new OkHttpClient.Builder()
// 大小是bytes
.cache(new Cache(new File("xx/xxx/"), 20 * 1024))
.build();
Okhttp僅支持get請(qǐng)求緩存哦,其他請(qǐng)求方式需要自己實(shí)現(xiàn)
超時(shí)設(shè)置
okhttp超時(shí)分為連接超時(shí)、讀取超時(shí)、寫入超時(shí)
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.connectTimeout(10, TimeUnit.SECONDS)
.pingInterval(10, TimeUnit.SECONDS) // websocket 輪訓(xùn)間隔
.build();
Cookie保存
Cookie的保存也提供了快捷方式,當(dāng)然也可以通過攔截器自己實(shí)現(xiàn)
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) {
// 從保存位置讀取,注意此處不能為空,否則會(huì)導(dǎo)致空指針
return new ArrayList<>();
}
})
.build();
添加攔截器
okhttp3的實(shí)現(xiàn)使用的是鏈?zhǔn)降臄r截器,同時(shí)也開放了自定義攔截器接口
OkHttpClient okHttpClient = new OkHttpClient.Builder()
// 此種攔截器將會(huì)在請(qǐng)求開始的時(shí)候調(diào)用
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
// 略
return null;
}
})
// 連接成功,讀寫數(shù)據(jù)前調(diào)用
.addNetworkInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
// 略
return null;
}
})
.build();
Https
okhttp3完全支持https,只要設(shè)置好證書即可
OkHttpClient okHttpClient = new OkHttpClient.Builder()
// 創(chuàng)建一個(gè)證書工廠
.sslSocketFactory(SSLSocketFactory, X509TrustManager)
.build();
GET
// 1.創(chuàng)建一個(gè)OkHttpClient,通常是單例,如果要自定義一些屬性那就要用內(nèi)部的Builder來構(gòu)造
/**
* OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor() //請(qǐng)求前的攔截器
.addNetworkInterceptor() // 網(wǎng)絡(luò)攔截器
.cache() // 緩存目錄
.connectTimeout() // 連接超時(shí)
.cookieJar() // cookie的讀取,保存,需要自己實(shí)現(xiàn)
.sslSocketFactory() // https證書
...略...
.build();
*/
OkHttpClient client = new OkHttpClient();
String run(String url) throws IOException {
// 2. 創(chuàng)建一個(gè)request,包含請(qǐng)求地址、請(qǐng)求參數(shù)、請(qǐng)求頭等
Request request = new Request.Builder()
.url(url)
.build();
// 3. 同步請(qǐng)求,得到響應(yīng)
Response response = client.newCall(request).execute();
return response.body().string();
}
POST
// 1.創(chuàng)建OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.build();
// 2.創(chuàng)建請(qǐng)求參數(shù),注意,此處有多種方式
RequestBody requestBody = new FormBody.Builder()
.add("param", "value")
.build();
// 3.創(chuàng)建請(qǐng)求request
Request request = new Request.Builder()
.url("https://wwww.xxx.com")
.post(requestBody)
.build();
// 4.發(fā)起請(qǐng)求,此處使用的是異步請(qǐng)求,按需要選擇同步或異步
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.處理相響應(yīng)
}
});
上傳文件
上傳文件本質(zhì)上是post請(qǐng)求,區(qū)別是在參數(shù)類型上
不要忘記權(quán)限,6.0(api23)動(dòng)態(tài)權(quán)限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
// 1.創(chuàng)建OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.build();
// 不同點(diǎn)
// 2.創(chuàng)建請(qǐng)求參數(shù),設(shè)置對(duì)應(yīng)的參數(shù)類型即可
RequestBody requestBody = RequestBody.create(MediaType.parse("text/x-markdown; charset=utf-8"), new File("xxx.txt"));
// 3.創(chuàng)建請(qǐng)求request
Request request = new Request.Builder()
.url("https://wwww.xxx.com")
.post(requestBody)
.build();
// 4.發(fā)起請(qǐng)求
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.處理相響應(yīng)
}
});
Multipart文件
multipart文件同上傳文件,區(qū)別是它可以同時(shí)有字符參數(shù),也可以有文件
// 1.創(chuàng)建OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.build();
// 不同點(diǎn)
// 2.創(chuàng)建請(qǐng)求參數(shù),設(shè)置對(duì)應(yīng)的參數(shù)類型即可
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.創(chuàng)建請(qǐng)求request
Request request = new Request.Builder()
.url("https://wwww.xxx.com")
.post(requestBody)
.build();
// 4.發(fā)起請(qǐng)求
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.處理相響應(yīng)
}
});
Websocket
okhttp3支持websocket,如果不了解請(qǐng)自行搜索,簡(jiǎn)易推送,輪訓(xùn)都可以使用。
websocket協(xié)議首先會(huì)發(fā)起http請(qǐng)求,握手成功后,轉(zhuǎn)換協(xié)議保持長(zhǎng)連接,類似心跳
// 方法可以選擇實(shí)現(xiàn)
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);
// 當(dāng)收到文本消息
}
@Override
public void onOpen(WebSocket webSocket, Response response) {
super.onOpen(webSocket, response);
// 連接成功
}
@Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
super.onMessage(webSocket, bytes);
// 收到字節(jié)消息,可轉(zhuǎn)換為文本
}
@Override
public void onClosed(WebSocket webSocket, int code, String reason) {
super.onClosed(webSocket, code, reason);
// 連接被關(guān)閉
}
@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
super.onFailure(webSocket, t, response);
// 連接失敗
}
});
混淆
在混淆文件(proguard-rules.pro)中添加如下語(yǔ)句:
-dontwarn okhttp3.**
總結(jié)
Okhttp3已經(jīng)成為android必備的網(wǎng)絡(luò)請(qǐng)求庫(kù),同時(shí)也是比較好用的庫(kù),對(duì)于更多Okhttp的實(shí)現(xiàn)細(xì)節(jié),請(qǐng)看下節(jié)
系列文章
3、關(guān)于Okhttp3(三)-請(qǐng)求流程](http://lowett.com/2017/02/13/okhttp-2/)