在項(xiàng)目中用的是Okhttp 3.4.2,替換原有的網(wǎng)絡(luò)框架奄容,okhttp使用很方便,封裝性很好产徊,在此紀(jì)錄一下使用過(guò)程中遇到的問(wèn)題昂勒。
1.返回?cái)?shù)據(jù)亂碼的問(wèn)題
由于服務(wù)器返回的數(shù)據(jù)本身就是Gzip格式,原有的網(wǎng)絡(luò)框架也是請(qǐng)求服務(wù)端返回Gzip格式舟铜,替換為okhttp后戈盈,照常添加addHeader("Accept-Encoding", "gzip, deflate"),結(jié)果服務(wù)器返回亂碼谆刨,無(wú)論怎么處理塘娶,試過(guò)轉(zhuǎn)換成字節(jié),編碼格式替換為gb2312痊夭,轉(zhuǎn)換成流處理血柳,都沒(méi)有用,客戶端得到的異常如下:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected
BEGIN_OBJECT but was STRING at line 1 column 1
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException:
Expected BEGIN_OBJECT but was STRING at line 1 column 1
第二天早上坐車(chē)去公司的路上生兆,查了一下google,無(wú)意中想到會(huì)不會(huì)是Gzip沒(méi)有解壓導(dǎo)致的膝宁,但是Okhttp又是對(duì)Gzip自動(dòng)支持并且自動(dòng)解壓的鸦难,最后查了源碼,才算明白是怎么回事员淫。
// If we add an "Accept-Encoding: gzip" header field we're responsible for also decompressing
// the transfer stream.
boolean transparentGzip = false;
if (userRequest.header("Accept-Encoding") == null)
{
transparentGzip = true;
requestBuilder.header("Accept-Encoding", "gzip");
}
if (transparentGzip &&
"gzip".equalsIgnoreCase(networkResponse.header("Content-Encoding"))
&& HttpHeaders.hasBody(networkResponse))
{
GzipSource responseBody = new GzipSource(networkResponse.body().source());
Headers strippedHeaders = networkResponse.headers().newBuilder()
.removeAll("Content-Encoding")
.removeAll("Content-Length")
.build();
responseBuilder.headers(strippedHeaders);
responseBuilder.body(new RealResponseBody(strippedHeaders, Okio.buffer(responseBody)));
}
上段代碼摘自BridgeInterceptor類(lèi)中合蔽,現(xiàn)在明白為什么了嗎?如果Request的header中用戶加了header("Accept-Encoding")的話介返,那么Okhttp不會(huì)幫你處理Gzip的解壓拴事,需要你自己去處理。那么問(wèn)題就好辦了圣蝎,把Request的header中去掉header("Accept-Encoding")就行了刃宵,調(diào)試不再出現(xiàn)亂碼,完美徘公。
2.怎么取消一次Request請(qǐng)求
原有的網(wǎng)絡(luò)請(qǐng)求庫(kù)中牲证,部分Api做了cancel的操作,那替換成了okhttp之后关面,怎么把這部分做一個(gè)處理呢坦袍?
還好okhttp可以通過(guò)Request.Builder.tag("url")來(lái)打tag十厢,然后通過(guò)下述代碼即可做到cancel某一個(gè)Request的功能,你需要做的只是返回url就行了捂齐。
public static void cancelCallWithTag(String tag) {
for (Call call : RequestApi2.getInstance().getOkHttpClient().dispatcher().queuedCalls()) {
if (call.request().tag().equals(tag))
call.cancel();
}
for (Call call : RequestApi2.getInstance().getOkHttpClient().dispatcher().runningCalls()) {
if (call.request().tag().equals(tag))
call.cancel();
}
}
3.順便紀(jì)錄一下Post中生成RequestBody的兩種方式
FormBody.Builder formBuilder = new FormBody.Builder();
RequestBody requestBody = formBuilder.build();
//對(duì)于Json的字符串蛮放,可以用這種方式
final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody.create(JSON, data)