okhttp3添加日志采集功能

日志采集是一個(gè)APP必備的功能,可以方便開發(fā)人員快速定位問題,解決問題,那么我們?cè)谑褂?a target="_blank" rel="nofollow">okhttp的時(shí)候應(yīng)該怎樣添加日志功能呢?

直接上干貨

    private class LogInterceptor implements Interceptor {
        @Override
        public okhttp3.Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            Log.v(TAG, "request:" + request.toString());
            long t1 = System.nanoTime();
            okhttp3.Response response = chain.proceed(chain.request());
            long t2 = System.nanoTime();
            Log.v(TAG, String.format(Locale.getDefault(), "Received response for %s in %.1fms%n%s",
                    response.request().url(), (t2 - t1) / 1e6d, response.headers()));
            okhttp3.MediaType mediaType = response.body().contentType();
            String content = response.body().string();
            Log.i(TAG, "response body:" + content);
            return response.newBuilder()
                    .body(okhttp3.ResponseBody.create(mediaType, content))
                    .build();
        }
    }
    ...
    OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .addInterceptor(new LogInterceptor())
                .build();

首先我們實(shí)現(xiàn)了一個(gè)攔截器LogInterceptor,里面做了三件事情:打印request內(nèi)容->執(zhí)行request->打印response內(nèi)容,過程簡(jiǎn)單清晰。但是有一個(gè)地方需要注意一下,在調(diào)用了response.body().string()方法之后,response中的流會(huì)被關(guān)閉,我們需要?jiǎng)?chuàng)建出一個(gè)新的response給應(yīng)用層處理通過response.peekBody()方法復(fù)制了一個(gè)ResponseBody,使用這個(gè)臨時(shí)的ResponseBody來打印body的內(nèi)容,而不是直接使用response.body().string()(此方法在header的content-length不確定的情況下會(huì)出錯(cuò),感謝苦逼鍵盤男kkmike999的指正)。手快的同學(xué)已經(jīng)敲完了代碼并驗(yàn)證了一遍,發(fā)現(xiàn)攔截器中能獲取到body的內(nèi)容,但是在攔截器外面就獲取不到了。

這是為什么呢?Talk is cheap show me the code。先看一下response.body().string()的實(shí)現(xiàn)

  public final String string() throws IOException {
    return new String(bytes(), charset().name());
  }

string()調(diào)用了bytes()來獲取內(nèi)容

  public final byte[] bytes() throws IOException {
    //省略部分代碼
    BufferedSource source = source();
    byte[] bytes;
    try {
      bytes = source.readByteArray();
    } finally {
      Util.closeQuietly(source);
    }
    //省略部分代碼
    return bytes;
  }

bytes()方法中先得到了BufferedSource,然后將BufferedSource中的內(nèi)容讀取出來,最后將BufferedSource中的文件流關(guān)閉,似乎并沒有什么問題。等等,我們?cè)跀r截器中將BufferedSource中的文件流關(guān)閉,而在ResponseBody中沒有相應(yīng)的數(shù)據(jù)緩存,所以我們?cè)跀r截器外部再想獲取body的內(nèi)容就失敗了,一切終于真相大白。

可以看到,我們?cè)跀r截器中相當(dāng)于手動(dòng)處理了網(wǎng)絡(luò)請(qǐng)求的整個(gè)過程,這就意味著在攔截器中可以做非常多的事情,例如虛擬一個(gè)返回結(jié)果等等,這些就不是本文的內(nèi)容了。

Update
使用Logging Interceptor可以很輕松的實(shí)現(xiàn)日志采集功能,具體細(xì)節(jié)參考

參考內(nèi)容:
[1]. https://github.com/square/okhttp/wiki/Interceptors

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容