OkHttp3
okHttp3 是一個 Android的基於Http的網絡開源框架,是由 square 公司開發。
現在網上比較推薦的兩個 Android 網絡開源框架,一個是 okHttp,另一個是 Retrofit
,而 Retrofit 是根據 okHttp封裝的框架。所以關於Android網絡部分,okHttp是必須要學習的一個知識。
[官網地址] (https://github.com/square/okhttp)
項目中引用 okHttp3 只需要在 app 的 build.gradle 中引用 compile ‘com.squareup.okhttp3:okhttp:3.6.0’ 即可。
[慕課網洪洋大神的okHttp視頻]
(http://www.imooc.com/learn/764)
[參考的簡書文章]
(http://www.jianshu.com/p/964bb1b2d345)
[參考的CSDN文章]
(http://blog.csdn.net/itachi85/article/details/51190687)
1.okHttp3的基本用法
首先,不管是 Get 請求還是 Post 請求,同步或者異步,okHttp3的請求總體分爲三步:
- 構造出一個okHttp3下的Request對象
- 通過這個Request對象,構造出一個Call對象
- 調用這個call對象的同步或者異步方法執行網絡訪問
示例如下:
//構造出一個Request對象,address是訪問的服務器地址,當前示例是get方式訪問
Request request = new Request.Builder().url(address).get().build();
//通過上面的request對象,構造出一個Call對象,sOkHttpClient爲全局的OkHttpClient對象
Call call = sOkHttpClient.newCall(request);
//call執行enqueue(異步)或者execute(同步),callback爲異步執行時的回調對象
call.enqueue(callback);
2.okHttp3下的Get請求方式
/**
* Get請求方法
* @param view
*/
public void doGet(View view){
String address = baseUrl + "login?username=hblolj&password=123456";
HttpUtils.sendOkHttpRequestByGet(address, new Callback() {
//請求失敗的回調
@Override
public void onFailure(Call call, IOException e) {
Log.i(TAG, "onFailure: " + e.getMessage());
e.printStackTrace();
}
//請求成功的回調
@Override
public void onResponse(Call call, Response response) throws IOException {
//拿到服務器返回的數據
final String result = response.body().string();
Log.i(TAG, "onResponse: " + result);
//因爲是enqueue異步執行,所以只有在主線程中纔可以更新UI
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_result.setText(result);
}
});
}
});
}
/**
* HttpUtils中的Get請求方法
* @param address get方式的請求地址
* @param callback 回調對象
*/
public static void sendOkHttpRequestByGet(String address , Callback callback){
Request request = new Request.Builder().url(address).get().build();
Call call = sOkHttpClient.newCall(request);
call.enqueue(callback);
}
3.okHttp3下的Post請求方式(鍵值對型)
Tips:post請求默認的類型是:application/x-www-form-urlencoded
//在OkHttp3的源碼中FormBody 的源碼
private static final MediaType CONTENT_TYPE =
MediaType.parse("application/x-www-form-urlencoded");
根據 MediaType 的類型,post選擇對上傳的數據是否進行編碼處理。如果爲 multipart/form-data 類型表示上傳的是文件,則不用進行編碼處理。
/**
* Post請求方法
* @param view
*/
public void doPost(View view){
//登錄接口
String address = baseUrl + "login";
Map<String, String> map = new HashMap<>();
map.put("username", "hblolj");
map.put("password", "123456");
HttpUtils.sendOkHttpRequestByPost(address, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.i(TAG, "onFailure: " + e.getMessage());
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final String result = response.body().string();
Log.i(TAG, "onResponse: " + result);
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_result.setText(result);
}
});
}
}, map);
}
/**
* HttpUtils中的post請求方法
* @param address post請求的地址
* @param callback 回調對象
* @param maps post請求的參數
*/
public static void sendOkHttpRequestByPost(String address, Callback callback, Map<String, String> maps){
//根據參數中的maps拼裝出RequestBody,用來保存參數,默認的MediaType
RequestBody requestBody = new FormBody.Builder()
.add("username", maps.get("username"))
.add("password", maps.get("password"))
.build();
//將請求地址與請求參數設置給Request
Request request = new Request.Builder().url(address).post(requestBody).build();
//構造Call對象
Call call = sOkHttpClient.newCall(request);
//異步執行網絡訪問
call.enqueue(callback);
}
4.okHttp3下的Post請求方式(String型)
/**
* Post請求上傳字符串
* @param view
*/
public void doPostString(View view){
String address = baseUrl + "postString";
HttpUtils.sendOkHttpRequestByPostString(address, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.i(TAG, "onFailure: " + e.getMessage());
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final String result = response.body().string();
Log.i(TAG, "onResponse: " + result);
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_result.setText(result);
}
});
}
}, "我是通過PostString傳遞的字符內容");
}
/**
* Post上傳字符串方法
* @param address 服務器地址
* @param callback 回調對象
* @param value 上傳的字符串
*/
public static void sendOkHttpRequestByPostString(String address, Callback callback, String value){
//相對於鍵值對類型,這裏指定了MediaType
RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain;charset=utf-8"), value);
//構造Request
Request request = new Request.Builder().url(address).post(requestBody).build();
//構造Call
Call call = sOkHttpClient.newCall(request);
//異步執行
call.enqueue(callback);
}
5.okHttp3下的Post請求方式(File型)
/**
* Post請求上傳文件
* @param view
*/
public void doPostFile(View view){
String address = baseUrl + "postFile";
//從內存卡獲取文件
File file = new File(Environment.getExternalStorageDirectory(), "shareimg.png");
if (!file.exists()){
Log.i(TAG, "文件不存在");
tv_result.setText("文件不存在!");
return;
}
HttpUtils.sendOkHttpRequestByPostFile(address, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.i(TAG, "onFailure: " + e.getMessage());
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final String result = response.body().string();
Log.i(TAG, "onResponse: " + result);
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_result.setText(result);
}
});
}
}, file);
}
/**
* Post方法上傳文件
* @param address 完整的請求地址
* @param callback 回調對象
* @param file 上傳的文件對象
*/
public static void sendOkHttpRequestByPostFile(String address, Callback callback, File file){
//指定了MediaType爲application/octet-stream,並且傳入File生成requestBody
RequestBody requestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
//構造Request
Request request = new Request.Builder().url(address).post(requestBody).build();
//構造Call
Call call = sOkHttpClient.newCall(request);
//異步執行
call.enqueue(callback);
}
6.okHttp3下的文件上傳
/**
* okHttp3下的文件上傳
* @param view
*/
public void doUpload(View view){
String address = baseUrl + "uploadFile";
File file = new File(Environment.getExternalStorageDirectory(), "tagPicture.jpg");
if (!file.exists()){
Log.i(TAG, "文件不存在");
tv_result.setText("文件不存在!");
return;
}
HttpUtils.sendOkHttpRequestByUpload(address, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.i(TAG, "onFailure: " + e.getMessage());
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final String result = response.body().string();
Log.i(TAG, "onResponse: " + result);
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_result.setText(result);
}
});
}
}, file);
}
/**
* okHttp3下的文件時上傳
* @param address 訪問的地址
* @param callback 回調對象
* @param file 上傳的文件
*/
public static void sendOkHttpRequestByUpload(String address, Callback callback, File file){
//構造MultipartBody(複合Body)
MultipartBody multipartBody = new MultipartBody.Builder()
//配置上傳的類型
.setType(MultipartBody.FORM)
//上傳的普通鍵值對
.addFormDataPart("username", "hblolj")
.addFormDataPart("password", "123456")
//參數對應爲name, fileName, reuqestBody
.addFormDataPart("picture", "一張照片.jpg",
//構造文件類型RequestBody
RequestBody.create(MediaType.parse("application/octet-stream"), file))
.build();
//構造Request
Request request = new Request.Builder().url(address).post(multipartBody).build();
//構造Call
Call call = sOkHttpClient.newCall(request);
//異步執行
call.enqueue(callback);
}
7.okHttp3下的文件下載
/**
* okhttp3下的文件下載
* @param view
*/
public void doDownloadFile(View view){
//下載地址
String address = baseUrl + "files/picture.jpg";
HttpUtils.sendOkHttpRequestByDownloadFile(address, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.i(TAG, "onFailure: " + e.getMessage());
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//拿到服務器下載文件的輸入流
InputStream is = response.body().byteStream();
//本地新建文件
File file = new File(Environment.getExternalStorageDirectory(), "一張照片6666.jpg");
//拿到新建文件的輸出流
FileOutputStream fout = new FileOutputStream(file);
//模板代碼,將下載文件的輸入流寫到新建文件
int len = 0;
byte[] buf = new byte[128];
while((len = is.read(buf)) != -1){
fout.write(buf, 0, len);
}
fout.flush();
fout.close();
is.close();
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_result.setText("下載成功");
}
});
}
});
}
/**
* okhttp3下的文件下載
* 找到下載地址,就是普通的Get訪問
* @param address 下載地址
* @param callback 回調對象
*/
public static void sendOkHttpRequestByDownloadFile(String address, Callback callback){
Request request = new Request.Builder().url(address).get().build();
Call call = sOkHttpClient.newCall(request);
call.enqueue(callback);
}
8.okHttp3下的Session保持與緩存
/**
* 全局的okHttpClient
*/
private static OkHttpClient sOkHttpClient = new OkHttpClient.Builder().cookieJar(new CookieJar() {
private Map<String, List<Cookie>> cookieStore = new HashMap<String, List<Cookie>>();
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
//根據請求的host保存cookies到內存,達到session的保存
Log.d("HttpUtils", "host: " + url.host());
cookieStore.put(url.host(), cookies);
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
List<Cookie> cookies = cookieStore.get(url.host());
return cookies!=null?cookies : new ArrayList<Cookie>();
}
})
//設置連接超時時間
.connectTimeout(1500, TimeUnit.MILLISECONDS)
.readTimeout(2000, TimeUnit.MILLISECONDS)
.writeTimeout(2000, TimeUnit.MILLISECONDS)
//設置保存緩存的文件以及大小限制
.cache(new Cache(file , 10*1024*1024))
.build();
9.okHttp3的框架封裝
參考開始的推薦文章