主要是用來打印請求參數,請求地址和返回
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();