OkHttp 也已經出來很久了,相信大家也都在項目中使用了,今天來對 OkHttp 使用進行一個簡單的總結
一、概述
HTTP 是超文本傳輸協議,也是互聯網上應用最爲廣泛的一種網絡協議,高效的進行 HTTP 使用可以使你的東西更快的加載並節省帶寬
OkHttp 是 HTTP 客戶端的有效應用,OkHttp 處理了很多疑難雜症:
- 例如會從很多常用連接問題中自動恢復
- 如果你的服務器設置了多個 IP 地址,當第一個IP連接失敗的時候,OkHttp 會自動嘗試下一個 IP
- OkHttp 還處理了代理服務器問題和 SSL 握手失敗問題
- 支持 HTTP/2,HTTP/2 通過使用多路複用技術在一個單獨的 TCP 連接上支持併發,通過在一個連接上一次性發送多個請求來發送或接受數據
- 如果 HTTP/2 不可用,連接池複用技術也可以極大地減少延遲
使用 OkHttp 無需重寫您程序中的網絡代碼,OkHttp 實現了幾乎和 HttpURLConnection 一樣的 API,OkHttp 支持 Android2.3 及以上
官網地址:http://square.github.io/okhttp/
GitHub 地址:https://github.com/square/okhttp
二、使用教程詳解
首先使用前我們需要在 app 目錄級別下的 build.gradle 中添加:
compile 'com.squareup.okhttp3:okhttp:3.8.1'
1. 異步 GET 請求
進行網絡數據加載,想必第一個我們就得先來說 GET 請求,這裏我們如果是新建的項目別忘了添加網絡權限
<uses-permission android:name="android.permission.INTERNET" />
/**
* 異步Get請求
* @param view
*/
public void getRequest(View view) {
//創建 OkHttpClient 對象
OkHttpClient okHttpClient = new OkHttpClient();
//創建 Request
Request request = new Request.Builder()
.url("https://www.baidu.com/")
.build();
Call call = okHttpClient.newCall(request);
//發送請求
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e(TAG, "失敗------" + e.getLocalizedMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.e(TAG, "成功------" + response);
String result = response.body().string();
Log.e(TAG, result);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "請求成功", Toast.LENGTH_SHORT).show();
}
});
}
});
}
以上我們就完成了一個異步 Get 請求,首先創建了 Okhttp 對象,並構造了 Request 對象,並傳入了一個 url,主意這裏Request.Builder 還可以設置如 header、method 等的參數方法,然後通過 request 的對象去構造得到一個 Call 對象,最後我們調用Call 對象的 enqueue() 來執行,注意這裏也可以選擇同步 execute() 請求,將 call 加入到調度隊列,然後等待執行完成,在 Callback 中得到回調結果,這裏我們需要注意的就是,onResponse 回調的參數是 reponse,一般來說,如果我們希望獲得返回的是字符串,可以通過 response.body().string() 獲取,如果希望獲得返回的二進制節數組,則通過 response.body().bytes() 等
2. 異步POST請求
/**
* 異步Post請求
*
* @param view
*/
public void postRequest(View view) {
//創建 OkHttpClient 對象
OkHttpClient okHttpClient = new OkHttpClient();
//構建 RequestBody
RequestBody formBody = new FormBody.Builder()
.add("鍵", "值")
.build();
//構建 Request
Request request = new Request.Builder()
.url("https://www.baidu.com/")
.post(formBody)
.build();
Call call = okHttpClient.newCall(request);
//發送請求
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e(TAG, "失敗------" + e.getLocalizedMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.e(TAG, "成功------" + response);
String result = response.body().string();
Log.e(TAG, result);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "請求成功", Toast.LENGTH_SHORT).show();
}
});
}
});
}
這裏需要注意一下 OkHttp3 異步 POST 請求和 OkHttp2.x 有一點區別就是沒有 FormEncodingBuilder 這個類,替代它的就是FormBody,大家都知道,post 的時候,參數是包含在請求體中的,所以我們通過 FormBody 來添加多個 String 鍵值對,然後去構造 RequestBody,來完成我們 Request 的構造,後面的步驟基本就和 get 請求一樣了,還有就是這了提交的表單格式可以有多種
如果表單是 json:
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody body = RequestBody.create(JSON, "你的json");
如果數據包含文件:
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse("image/png"), file))
.build();
接下來我們將會講具體解到
3. 異步上傳文件
定義上傳文件得類型:
//上傳文件的類型
public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");
/**
* 異步上傳文件
*
* @param view
*/
public void postFile(View view) {
OkHttpClient okHttpClient = new OkHttpClient();
File file = new File("上傳的文件");
Request request = new Request.Builder()
.url("上傳的地址")
.post(RequestBody.create(MEDIA_TYPE_MARKDOWN,file))
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
}
這裏也要注意不要忘記添加權限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
可以看到上傳文件其實也是一個 POST 請求
4. 異步上傳 Multipart 文件
//定義類型
private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
/**
* 異步上傳Multipart文件
*/
public void sendMultipart() {
OkHttpClient okHttpClient = new OkHttpClient();
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("title", "nihao")
.addFormDataPart("image", "image.jpg", RequestBody.create(MEDIA_TYPE_PNG, new File("/sdcard/image.jpg")))
.build();
Request request = new Request.Builder()
.header("Authorization", "Client-ID " + "...")
.url("https://api.imgur.com/3/image")
.post(requestBody)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.i(TAG, response.body().string());
}
});
}
異步上傳文件這種場景在開發中還是很常用的,上傳不同類型的文件同時還需要傳其他類型的字段,這些用 OkHttp3 實現起來很簡單,這裏我們只是做了一個示例,實際開發中大家還要具體對應自己的服務器聯調
5. 異步下載文件
/**
* 異步下載文件
*
* @param view
*/
public void downFile(View view) {
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url("下載地址").build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) {
InputStream inputStream = response.body().byteStream();
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(new File("/sdcard/iamge.jpg"));
byte[] buffer = new byte[2048];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, len);
}
fileOutputStream.flush();
} catch (IOException e) {
Log.i(TAG, "IOException");
e.printStackTrace();
}
Log.d(TAG, "文件下載成功");
}
});
}
6. 設置超時時間和緩存
File sdcache = getExternalCacheDir();
int cacheSize = 10 * 1024 * 1024;
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.cache(new Cache(sdcache.getAbsoluteFile(), cacheSize));
OkHttpClient okHttpClient=builder.build();
這裏需要注意得是和 OkHttp2.x 不同的是,不能通過 OkHttpClient 直接設置超時和緩存了,而是通過 OkHttpClient.Builder 來設置,通過 builder 配置好 OkHttpClient 後用 builder.builder() 來返回 OkHttpClient
我們用到的大概也就這些了,都是一些比較基本的用法,在實際項目中,大家肯定還得進行進一步的封裝,要不這樣使用大家也看到了,怪累,今天就寫到這裏,有錯誤的地方請指出