1. 程式人生 > >OkHttp3的簡單使用(一)

OkHttp3的簡單使用(一)

獲得 enqueue css 界面 字節 cat read 註意事項 字符串

一、導入

1)gradle方式:

compile ‘com.squareup.okhttp3:okhttp:3.8.0‘(okhttp 最新版)

compile ‘com.squareup.okio:okio:1.13.0‘(okio最新版)

2)jar包導入

okhttp-3.3.0.jar
okio-1.8.0.jar

3)權限

<!--網絡訪問權限-->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- 外置存儲存取權限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

二、使用

同步:execute() 異步:enqueue(new Callback()...)

一)get請求

String url="http://www,baidu.com/";
OkHttpClient client=new OkHttpClient();
Request request=new Request.Builder()
.url(url)
.build();
Call call=client.newCall(request);

//同步
try {
Response response=call.execute();
if(response.isSuccessful()){
Log.e(TAG, "onCreate: "+response.body().string() );
}
} catch (IOException e) {
e.printStackTrace();
}

//異步
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//失敗
Log.e(TAG, "onFailure: 失敗:"+e.getMessage() );
}

@Override
public void onResponse(Call call, Response response) throws IOException {
//成功
Log.e(TAG, "onResponse: "+response.body().string() );
}
});

二)POST請求JSON格式

String url="http://www,baidu.com/";
OkHttpClient client=new OkHttpClient();

MediaType JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody body = RequestBody.create(JSON, "你的json");

Request request=new Request.Builder()
.url(url)
.post(requestBody)
.build();

Call call=client.newCall(request);

//同步
try {
Response response=call.execute();
if(response.isSuccessful()){
Log.e(TAG, "onCreate: "+response.body().string() );
}
} catch (IOException e) {
e.printStackTrace();
}

//異步
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//失敗
Log.e(TAG, "onFailure: 失敗:"+e.getMessage() );
}

@Override
public void onResponse(Call call, Response response) throws IOException {
//成功
Log.e(TAG, "onResponse: "+response.body().string() );
}
});

三)POST請求表單格式

post請求創建request和get是一樣的,只是post請求需要提交一個表單,就是RequestBody。表單的格式有好多種,普通的表單是:
RequestBody body = new FormBody.Builder()
.add("鍵", "值")
.add("鍵", "值")
...
.build();

普通表單:
RequestBody body = new FormBody.Builder()
.add("鍵", "值")
.add("鍵", "值")
...
.build();
FormBody繼承了RequestBody,它已經指定了數據類型為application/x-www-form-urlencoded
private static final MediaType CONTENT_TYPE = MediaType.parse("application/x-www-form-urlencoded");

四)上傳文件

//創建 MediaType 設置上傳文件類型
MediaType MEDIATYPE = MediaType.parse("text/plain; charset=utf-8");
//獲取請求體
RequestBody requestBody = RequestBody.create(MEDIATYPE, file);
//創建請求
Request request = new Request.Builder().url("http://www.baidu.com")
.post(requestBody)
.build();

五)上傳Multipart文件

//定義上傳文件類型
private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");

RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)//數據格式 帶有文件
.addFormDataPart("title", "wangshu") //鍵值對參數
.addFormDataPart("image", "wangshu.jpg",
RequestBody.create(MEDIA_TYPE_PNG, new File("/sdcard/wangshu.jpg"))) //要上傳的文件
.build();



RequestBody的數據格式都要指定Content-Type,常見的有三種:
application/x-www-form-urlencoded 數據是個普通表單
multipart/form-data 數據裏有文件
application/json 數據是個json

MediaType的創建:
MediaType MEDIATYPE = MediaType.parse("text/plain; charset=utf-8");

如果表單是個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("鍵","值”)
.addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse("image/png"), file))
.build();
另外如果你上傳一個文件不是一張圖片,但是MediaType.parse("image/png")裏的"image/png"不知道該填什麽,可以參考(http://www.w3school.com.cn/media/media_mimeref.asp)。


常見的文件類型:
參數 說明
text/html HTML格式
text/plain 純文本格式
text/xml XML格式
image/gif gif圖片格式
image/jpeg jpg圖片格式
image/png png圖片格式
application/xhtml+xml XHTML格式
application/xml XML數據格式
application/atom+xml Atom XML聚合格式
application/json JSON數據格式
application/pdf pdf格式
application/msword Word文檔格式
application/octet-stream 二進制流數據

六)設置超時時間和緩存

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 mOkHttpClient=builder.build();

七)添加請求頭

okhttp3添加請求頭,需要在Request.Builder()使用.header(String key,String value)或者.addHeader(String key,String value);
使用.header(String key,String value),如果key已經存在,將會移除該key對應的value,然後將新value添加進來,即替換掉原來的value;
使用.addHeader(String key,String value),即使當前的可以已經存在值了,只會添加新value的值,並不會移除/替換原來的值。
還有.headers(Headers headers)添加請求頭集合

Request request = new Request.Builder()
.url("https://api.github.com/repos/square/okhttp/issues")
.header("User-Agent", "OkHttp Headers.java")
.addHeader("Accept", "application/json; q=0.5")
.addHeader("Accept", "application/vnd.github.v3+json")
.build();

/**
* 設置請求頭
* @param headersParams
* @return
*/
private Headers SetHeaders(Map<String, String> headersParams){
Headers headers=null;
okhttp3.Headers.Builder headersbuilder=new okhttp3.Headers.Builder();

if(headersParams != null)
{
Iterator<String> iterator = headersParams.keySet().iterator();
String key = "";
while (iterator.hasNext()) {
key = iterator.next().toString();
headersbuilder.add(key, headersParams.get(key));
Log.d("get http", "get_headers==="+key+"===="+headersParams.get(key));
}
}
headers=headersbuilder.build();

return headers;
}

八)取消請求

使用call.cancel()可以立即停止掉一個正在準備的同步/異步請求call。如果一個線程正在寫請求或者讀響應,將會引發IOException。
當用戶離開一個應用時或者跳到其他界面時,使用Call.cancel()可以節約網絡資源,另外不管同步還是異步的call都可以取消。
也可以通過tags來同時取消多個請求。當你構建一請求時,使用RequestBuilder.tag(tag)來分配一個標簽。
之後你就可以用OkHttpClient.cancel(tag)來取消所有帶有這個tag的call。

九)自動管理Cookie

Request經常都要攜帶Cookie,上面說過request創建時可以通過header設置參數,Cookie也是參數之一。就像下面這樣:
Request request = new Request.Builder()
.url(url)
.header("Cookie", "xxx")
.build();

OkHttp可以不用我們管理Cookie,自動攜帶,保存和更新Cookie。
方法是在創建OkHttpClient設置管理Cookie的CookieJar:

private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.cookieJar(new CookieJar() {
@Override
public void saveFromResponse(HttpUrl httpUrl, List<Cookie> list) {
cookieStore.put(httpUrl.host(), list);
}

@Override
public List<Cookie> loadForRequest(HttpUrl httpUrl) {
List<Cookie> cookies = cookieStore.get(httpUrl.host());
return cookies != null ? cookies : new ArrayList<Cookie>();
}
})
.build();


這樣以後發送Request都不用管Cookie這個參數也不用去response獲取新Cookie什麽的了。還能通過cookieStore獲取當前保存的Cookie。
最後,new OkHttpClient()只是一種快速創建OkHttpClient的方式,更標準的是使用OkHttpClient.Builder()。後者可以設置一堆參數,例如超時時間什麽的。

註意事項

Android 4.0之後要求網絡請求必須在工作線程中運行,不允許在主線程中運行。因此如果使用OkHttp3的同步方法,需要新起工作線程進行調用。
一般情況下我們希望獲得Response返回的字符串,可以通過response.body().string()獲取;
如果希望獲得返回的二進制字節數組,則調用response.body().bytes();
如果想獲取到返回的InputStream,則調用response.body().byteStream()。
異步請求enqueue的回調是子線程,非主線程,所以是不能直接操作UI界面的。
響應體的string()方法適用於獲取小數據信息,如果返回的數據太大(超過1MB),
建議使用stream()獲取返回的數據,因為string()方法會將整個文檔加載到內存中。

參考:

http://blog.csdn.net/lmj623565791/article/details/47911083
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0106/2275.html
http://www.2cto.com/kf/201604/501946.html
http://blog.csdn.net/feixiang_gao/article/details/53760705
http://blog.csdn.net/chinaboyliusir/article/details/51261929
http://blog.csdn.net/wwwkp1236/article/details/51374320
https://github.com/MrZhousf/OkHttp3

OkHttp3的簡單使用(一)