您的当前位置:首页正文

okhttp3添加日志采集功能

来源:华拓网

直接上干货

    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();

这是为什么呢?Talk is cheap show me the code。先看一下response.body().string()的实现

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

string()调用了bytes()来获取内容

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

bytes()方法中先得到了BufferedSource,然后将BufferedSource中的内容读取出来,最后将BufferedSource中的文件流关闭,似乎并没有什么问题。等等,我们在拦截器中将BufferedSource中的文件流关闭,而在ResponseBody中没有相应的数据缓存,所以我们在拦截器外部再想获取body的内容就失败了,一切终于真相大白。

可以看到,我们在拦截器中相当于手动处理了网络请求的整个过程,这就意味着在拦截器中可以做非常多的事情,例如虚拟一个返回结果等等,这些就不是本文的内容了。