背景及問題
在使用Okhttp
時,經常會用到自定義的攔截器,對請求體Request
或返回體Response
做額外的處理。
在攔截器中,通常使用如下方式獲取Request
和Response
;
Request request = chain.request();//獲取請求
Response response = chain.proceed(request);//處理請求,獲取響應體
在處理Response
時,通常會對Response
中的返回體內容進行日誌輸出或者是內容判斷等。爲了獲取請求體中的內容通常使用string()
函數獲取;
Response response = chain.proceed(request);
String bodyStr = response.body().string();
在通過string()
函數獲取返回體中的字符串以後,當我們嘗試用同一個Response
對象再次使用string()
函數獲取返回體的內容時,此時獲取的內容返回爲空字符串。
string()
在string()
函數被調用後,Response
返回體body()
中的所有字節都會被移除,其源碼如下:
//:ResponseBody.java
public final String string() throws IOException {
BufferedSource source = this.source();
String var3;
try {
Charset charset = Util.bomAwareCharset(source, this.charset());
var3 = source.readString(charset);
} finally {
Util.closeQuietly(source);
}
return var3;
}
//:BufferedSource.java
/** Removes all bytes from this, decodes them as {@code charset}, and returns the string. */
String readString(Charset charset) throws IOException;
解決方法
在掉用string()
後,使用返回體的String
等信息重新創建新的Response
對象;
private Response login(Response response) {
try {
Response.Builder builder = response.newBuilder();
Response clone = builder.build();
ResponseBody body = clone.body();
if (body != null) {
MediaType mediaType = body.contentType();
if (mediaType != null) {
if (isText(mediaType)) {
String resp = body.string();
XLog.d(resp);//在這裏輸出請求體內容
//創建新的response
body = ResponseBody.create(mediaType, resp);
//在調用完string()後只有body()的內容清空,所以可以藉助newBuilder手動添加body()來新建一個Response對象,對外部而言這兩個response是沒有區別的
return response.newBuilder()
.body(body)
.build();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return response;
}