在做处理网络请求的时候,可以直观的看到每次请求的传参和响应是非常有帮助的。
public static API get() {
if (api == null) {
synchronized (Retrofit.class) {
if (api == null) {
OkHttpClient httpClient = new OkHttpClient
.Builder()
.addInterceptor(new RequestLoggerInterceptor())
.addInterceptor(new ResponseLogInterCeptor())
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API.BASE_URL)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient)
.build();
api = retrofit.create(API.class);
}
}
}
return api;
}
请求的拦截器非常简单
static class RequestLoggerInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Log.d(TAG, "url = : " + request.url());
Log.d(TAG, "method = : " + request.method());
Log.d(TAG, "headers = : " + request.headers());
Log.d(TAG, "body = : " + request.body());
return chain.proceed(request);
}
}
而响应的拦截器需要考虑body()
只能被调用一次的问题,开始的时候我单纯的以为这样就可以
static class responseLogInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
Log.d(TAG, "code = : " + response.code());
Log.d(TAG, "message = : " + response.message());
Log.d(TAG, "protocol = : " + response.protocol());
Log.d(TAG, "string = : " + response.body().string());
Response clone = response.newBuilder().build();
return clone;
}
}
开始以为这样就是clone
了一个Response
对象,后来发现太年轻了
public Builder newBuilder() {
return new Builder(this);
}
Builder(Response response) {
this.request = response.request;
this.protocol = response.protocol;
this.code = response.code;
this.message = response.message;
this.handshake = response.handshake;
this.headers = response.headers.newBuilder();
this.body = response.body;
this.networkResponse = response.networkResponse;
this.cacheResponse = response.cacheResponse;
this.priorResponse = response.priorResponse;
this.sentRequestAtMillis = response.sentRequestAtMillis;
this.receivedResponseAtMillis = response.receivedResponseAtMillis;
}
public Response build() {
if (request == null) throw new IllegalStateException("request == null");
if (protocol == null) throw new IllegalStateException("protocol == null");
if (code < 0) throw new IllegalStateException("code < 0: " + code);
if (message == null) throw new IllegalStateException("message == null");
return new Response(this);
}
同一个body
嘛。
稍微改一下
static class ResponseLogInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
Log.d(TAG, "code = : " + response.code());
Log.d(TAG, "message = : " + response.message());
Log.d(TAG, "protocol = : " + response.protocol());
if (response.body() != null && response.body().contentType() != null) {
MediaType mediaType = response.body().contentType();
String string = response.body().string();
Log.d(TAG, "mediaType = : " + mediaType.toString());
Log.d(TAG, "string = : " + string);
ResponseBody responseBody = ResponseBody.create(mediaType, string);
return response.newBuilder().body(responseBody).build();
} else {
return response;
}
}
}
关键在于response.newBuilder().body(responseBody).build();
这里传入了一个新构建的body
。这样才能保证在后续操作中调用body.string()
不会抛出异常。
当然在输入body().string()
的时候,还要做MediaType
的类型判断