网络Android技术知识Android知识

OkHttp:拦截器之网络请求Log

2016-10-21  本文已影响495人  Aracys

主要是用来打印请求参数,请求地址和返回json的拦截器封装

最近研究了Retrofit感觉不错,但是如果有自己封装的框架应该更好点,会更适合自己的开发。用这个写了个小demo发现个问题,封装后找不到打印和请求参数的地方了,后来想到了拦截器,分析后封装了个,这个拦截器只有打印功能,隐藏在发布版可以直接去掉这个类

import android.util.Log;
import java.io.IOException;
import java.nio.charset.Charset;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;


import static okhttp3.internal.Util.UTF_8;

public class LoggerInterceptor implements Interceptor {

    public static final String TAG = "NetWorkLogger";

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        printRequestMessage(request);
        Response response = chain.proceed(request);
        printResponseMessage(response);
        return response;
    }
    /**
     * 打印请求消息
     *
     * @param request 请求的对象
     */
    private void printRequestMessage(Request request) {
        if (request == null) {
            return;
        }
        Log.i(TAG, "Url   : " + request.url().url().toString());
        Log.i(TAG, "Method: " + request.method());
        Log.i(TAG, "Heads : " + request.headers());
        RequestBody requestBody = request.body();
        if (requestBody == null) {
            return;
        }
        try {
            Buffer bufferedSink = new Buffer();
            requestBody.writeTo(bufferedSink);
            Charset charset = requestBody.contentType().charset();
            charset = charset == null ? Charset.forName("utf-8") : charset;
            Log.i(TAG, "Params: " + bufferedSink.readString(charset));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 打印返回消息
     *
     * @param response 返回的对象
     */
    private void printResponseMessage(Response response) {
        if (response == null || !response.isSuccessful()) {
            return;
        }
        ResponseBody responseBody = response.body();
        long contentLength = responseBody.contentLength();
        BufferedSource source = responseBody.source();
        try {
            source.request(Long.MAX_VALUE); // Buffer the entire body.
        } catch (IOException e) {
            e.printStackTrace();
        }
        Buffer buffer = source.buffer();
        Charset charset = UTF_8;
        MediaType contentType = responseBody.contentType();
        if (contentType != null) {
            charset = contentType.charset();
        }
        if (contentLength != 0) {
            String result = buffer.clone().readString(charset);
            Log.i(TAG, "Response: " + result);
        }
    }
}

当然其中也有不少小坑,参考了部分博客总算解决了。比较要注意的就是打印返回值的时候,如果直接获取值打印的话,就会讲流关闭,下次就不能再去取了,最总结果就是在回调的时候你不能去获取返回值。解决方法也不难,就是先clone一份,然后再去获取值,打印出来就好了,比较麻烦的就是ResponseBody不能直接去clone,要去内部获取source再去clone读取

使用比较简单,直接上代码

OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .addInterceptor(new LoggerInterceptor())
        .build();

这个暂时不能设置为网络拦截器,否则返回的JSON会乱码,猜测可能是网络拦截器所在的位置还没有处理好,暂时还不是可读取的格式,或者是还在压缩状态,有兴趣的同学可以研究下

如果是使用Retrofit,直接讲client添加为CallFactory就可以了:

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://192.168.1.73:8081/Apis/")
        .addConverterFactory(GsonConverterFactory.create())
        .callFactory(okHttpClient1)
        .build();
上一篇下一篇

猜你喜欢

热点阅读