解決Okhttp的Response#body()#string()後Response返回體爲空問題

背景及問題

在使用Okhttp時,經常會用到自定義的攔截器,對請求體Request或返回體Response做額外的處理。
在攔截器中,通常使用如下方式獲取RequestResponse;

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;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章