http請(qǐng)求主要是Get和Post。二者都分為的同步和異步請(qǐng)求。
Get和Post的區(qū)別:
Get用來(lái)做簡(jiǎn)單的數(shù)據(jù)請(qǐng)求,請(qǐng)求的數(shù)據(jù)寫在地址上,比如:
http://m.itdecent.cn/search?q=bilibili&page=1&type=notes
其中http://m.itdecent.cn/ 是主機(jī)地址search后面的?q=bilibili&page=1&type=notes 是你的請(qǐng)求信息,以鍵值對(duì)的形式直接加載地址上,用&符號(hào)隔開(kāi),任何人都看得到。所以GET請(qǐng)求是不安全的。一般不重要的請(qǐng)求,并且你的請(qǐng)求信息的數(shù)據(jù)量不大的就可以用GET請(qǐng)求。
POST算是GET請(qǐng)求的升級(jí)版。它將請(qǐng)求信息寫在RequestBody里面,RequestBody可以裝很多東西,比如GET請(qǐng)求的鍵值對(duì)信息,用戶賬號(hào)登錄就可以用POST請(qǐng)求啦。也可以上傳文件,這些是GET請(qǐng)求不能的。
OkHttp 請(qǐng)求流程:(基于okhttp3)
1 . 創(chuàng)建OkhttpClient。(注:全局最好只創(chuàng)建1個(gè)OkHttpClient,推薦使用單例模式創(chuàng)建)
OkhttpClient mClient = new OkhttpClient();
2 . mClient執(zhí)行newCall將Request轉(zhuǎn)化成一個(gè)Call。Request后面再說(shuō)。
Call call = mClient.newCall(Request request)
3 . 最后call執(zhí)行excute同步執(zhí)行,enqueue異步執(zhí)行
call.enqueue(Callback calBack)//異步執(zhí)行
或者Response res = call.excute();//線程阻塞
3.1 Callback中重寫兩個(gè)方法
new Callback() {
@Override public void onFailure(Request request, Throwable throwable) {
throwable.printStackTrace();
}
@Override public void onResponse(Response response) throws IOException {
//對(duì)response處理
}
3.2 上面的Response代表Http請(qǐng)求的響應(yīng)。
- response.body()是ResponseBody類代表響應(yīng)體,可以通過(guò)responseBody.string()獲得字符串的表達(dá)形式。
- responseBody.bytes()獲得字節(jié)數(shù)組的表達(dá)形式, 這兩種形式都會(huì)把文檔加入到內(nèi)存。
- 也可以通過(guò)responseBody.charStream()和responseBody.byteStream()返回流來(lái)處理。
4 . Request主要通過(guò)Request.Builder來(lái)構(gòu)建
Request.Builder() builder = new Request.Builder();
GET請(qǐng)求
Request request = builder.url(url)//請(qǐng)求地址
.get()//請(qǐng)求方法,不寫默認(rèn)GET方法
.build();
POST請(qǐng)求
Request request = builder.url(url)
.Post(RequestBody requestBody)//這個(gè)就是請(qǐng)求體
.build();
4.1 RequestBody的構(gòu)建
從需求分析有:表單提交、文件提交,字符串,前面幾種的組合提交。
- 表單
RequestBody requestBody = new FormBody.Builder()
.add("q", "bilibili")//此處應(yīng)為鍵值對(duì)
.add("page","1")
.build();
- 字符串
RequestBody requestBody = RequestBody.create(mMediaType, string)
//POST提交文件需要請(qǐng)求頭里加上文件的類型
//MediaType表示了文件類型
//可以這樣寫 ,表示是text中的x-markdowm類型,字符集為UTF-8
//MediaType mMediaType = MediaType.parse("text/x-markdown; charset=utf-8");
- 文件
File file = new File();
RequestBody requestBody = RequestBody.create(mMediaType, file)
- io流
RequestBody requestBody = new RequestBody() {
@Override public MediaType contentType() {
return mMediaType;
}
@Override public void writeTo(BufferedSink sink) throws IOException {
//sink上傳數(shù)據(jù)流
}
}
- 組合分塊提交
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("title", "name")
.addFormDataPart("image", "icon.jpg",RequestBody.create(mMediaType, new File(".../icon.jpg")))
.build();
//本次提交了用戶名和圖片
5. 緩存
在創(chuàng)建OKHttpClient后調(diào)用OKHttpClient .setCache(Cache cache)可以設(shè)置緩存。也可以使用OkHttpClient.Builder設(shè)置更多其他屬性。
File cache = getExternalCacheDir();
int cacheSize = 10 * 1024 * 1024;//10M
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)//超時(shí)
.writeTimeout(20, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.cache(new Cache(cache.getAbsoluteFile(), cacheSize));
OkHttpClient mOkHttpClient=builder.build();
在使用了緩存后,如果已經(jīng)緩存了請(qǐng)求結(jié)果,第二次將直接讀取緩存,而不會(huì)連接網(wǎng)絡(luò)再次請(qǐng)求。當(dāng)我們需要網(wǎng)站數(shù)據(jù)更新了就獲取不了最新數(shù)據(jù),所以在Request.Builder中可以使用chacheControl(ChacheControl.FORCE_NETWORK )讓Request強(qiáng)制使用網(wǎng)絡(luò)獲取數(shù)據(jù)而不使用緩存。將ChacheControl.FORCE_NETWORK換成ChacheControl.FORCE_CACHE就是強(qiáng)制使用緩存。但是,如果沒(méi)有緩存的話,就報(bào)504錯(cuò)誤。(Request.Builder除了new一個(gè)以外,還可以通過(guò)已存在的request.newBuilder()得到)
6. 取消請(qǐng)求
當(dāng)一個(gè)call執(zhí)行了enqueue()或者excute()還沒(méi)執(zhí)行完畢,比如onResponse還沒(méi)執(zhí)行,就可以使用call.cancel()取消請(qǐng)求。否則會(huì)IOException。