Android日志拦截器,Retrofit使用详解(五)添加日志拦截器

输出请求日志和响应日志

Retrofit在网络层完全依赖于OkHttp,有人为它做了一个日志拦截器来输出日志,首先在gradle中添加依赖:

compile 'com.squareup.okhttp3:logging-interceptor:3.3.1'

为OkHttp添加拦截器

HttpLoggingInterceptor logging = new HttpLoggingInterceptor();

// set your desired log level

logging.setLevel(Level.BODY);

OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

// add your other interceptors …

// add logging as last interceptor

httpClient.addInterceptor(logging); //

Retrofit retrofit = new Retrofit.Builder()

.baseUrl(API_BASE_URL)

.addConverterFactory(GsonConverterFactory.create())

.client(httpClient.build())

.build();

推荐把输出日志的拦截器放在其他拦截器的后面,这样就会打印出所有的内容。

Log Levels

OkHttp的日志输出有四个级别:

NONE

BASIC

HEADERS

BODY

None

没有日志输出。

Basic

日志会输出请求类型(request type),请求地址(url),请求大小(size of request body),响应码(response status)响应大小(size of response body)。

D/HttpLoggingInterceptor$Logger: --> POST /upload HTTP/1.1 (277-byte body)

D/HttpLoggingInterceptor$Logger:

Headers

输出请求和响应的头信息(headers),请求类型(request type),请求地址(request url),响应码(response status)。

使用HEADERS日志级别只会记录请求和响应的头信息。Retrofit或OkHttp会默认添加相应的请求头,但它们不会显示在您的请求上,因为它们稍后会添加到请求链中。 如果自己添加请求头,请确保日志拦截器是添加到OkHttp客户端的最后一个拦截器。 如果您第一个添加拦截器,请求上尚未设置任何头数据。

我们使用两个头字段Accept和Content-Type来说明输出:

D/HttpLoggingInterceptor$Logger: --> POST /upload HTTP/1.1

D/HttpLoggingInterceptor$Logger: Accept: application/json

D/HttpLoggingInterceptor$Logger: Content-Type: application/json

D/HttpLoggingInterceptor$Logger: --> END POST

D/HttpLoggingInterceptor$Logger:

D/HttpLoggingInterceptor$Logger: content-type: text/html; charset=utf-8

D/HttpLoggingInterceptor$Logger: cache-control: no-cache

D/HttpLoggingInterceptor$Logger: vary: accept-encoding

D/HttpLoggingInterceptor$Logger: Date: Wed, 28 Oct 2015 08:24:20 GMT

D/HttpLoggingInterceptor$Logger: Connection: keep-alive

D/HttpLoggingInterceptor$Logger: Transfer-Encoding: chunked

D/HttpLoggingInterceptor$Logger: OkHttp-Selected-Protocol: http/1.1

D/HttpLoggingInterceptor$Logger: OkHttp-Sent-Millis: 1446020610352

D/HttpLoggingInterceptor$Logger: OkHttp-Received-Millis: 1446020610369

D/HttpLoggingInterceptor$Logger:

除了服务器响应的头信息,还会输出选择协议的信息以及发送请求和接收响应时的相应毫秒数。

Body

输出请求和响应的头信息(headers)和内容(body)。

这是您将获得响应正文数据的唯一日志级别。 仅在必要时使用此级别。

D/HttpLoggingInterceptor$Logger: --> POST /upload HTTP/1.1

D/HttpLoggingInterceptor$Logger: --9df820bb-bc7e-4a93-bb67-5f28f4140795

D/HttpLoggingInterceptor$Logger: Content-Disposition: form-data; name="description"

D/HttpLoggingInterceptor$Logger: Content-Transfer-Encoding: binary

D/HttpLoggingInterceptor$Logger: Content-Type: application/json; charset=UTF-8

D/HttpLoggingInterceptor$Logger: Content-Length: 37

D/HttpLoggingInterceptor$Logger:

D/HttpLoggingInterceptor$Logger: "hello, this is description speaking"

D/HttpLoggingInterceptor$Logger: --9df820bb-bc7e-4a93-bb67-5f28f4140795--

D/HttpLoggingInterceptor$Logger: --> END POST (277-byte body)

D/HttpLoggingInterceptor$Logger:

D/HttpLoggingInterceptor$Logger: content-type: text/html; charset=utf-8

D/HttpLoggingInterceptor$Logger: cache-control: no-cache

D/HttpLoggingInterceptor$Logger: vary: accept-encoding

D/HttpLoggingInterceptor$Logger: Date: Wed, 28 Oct 2015 08:33:40 GMT

D/HttpLoggingInterceptor$Logger: Connection: keep-alive

D/HttpLoggingInterceptor$Logger: Transfer-Encoding: chunked

D/HttpLoggingInterceptor$Logger: OkHttp-Selected-Protocol: http/1.1

D/HttpLoggingInterceptor$Logger: OkHttp-Sent-Millis: 1446021170095

D/HttpLoggingInterceptor$Logger: OkHttp-Received-Millis: 1446021170107

D/HttpLoggingInterceptor$Logger: Perfect!

D/HttpLoggingInterceptor$Logger:

只在开发环境下输出日志

自动化是增强开发人员关注点和生产力的最佳工具之一。启用和禁用Retrofit的日志记录可能是一个繁琐,重复的任务。所以让我们自动化这个过程:在开发过程中,将为调试版本启用日志记录; 并且您的应用程序的所有生产版本的日志记录将被禁用!

解决方案很简单:我们将使用由Android框架提供的BuildConfig.DEBUG布尔变量。 它将为您的开发环境返回true,对于您的生产环境返回false。

OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

if (BuildConfig.DEBUG) {

HttpLoggingInterceptor logging = new HttpLoggingInterceptor();

logging.setLevel(Level.BODY);

httpClient.addInterceptor(logging);

}

Retrofit retrofit = new Retrofit.Builder()

.baseUrl(API_BASE_URL)

.addConverterFactory(GsonConverterFactory.create())

.client(httpClient.build())

.build();

使用不同级别的日志

OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

HttpLoggingInterceptor logging = new HttpLoggingInterceptor();

if (BuildConfig.DEBUG) {

// development build

logging.setLevel(Level.BODY);

} else {

// production build

logging.setLevel(Level.BASIC);

}

httpClient.addInterceptor(logging);

Retrofit retrofit = new Retrofit.Builder()

.baseUrl(API_BASE_URL)

.addConverterFactory(GsonConverterFactory.create())

.client(httpClient.build())

.build();

这样就可以在生产环境和正式环境中输出不同的日志了。

捕捉错误

在服务器发生错误或者用户输入的数据错误时,我们希望呈献给用户反馈信息,并要求他改正。

在这之前,我们来看一个简单的例子:

Error Object

首先我们创建一个错误json:

{

statusCode: 409,

message: "Email address already registered"

}

定义一个错误类

public class APIError {

private int statusCode;

private String message;

public APIError() {

}

public int status() {

return statusCode;

}

public String message() {

return message;

}

}

Simple Error Handler

我们将使用下面的类,返回一个APIError对象的静态方法。 parseError方法的参数为Response。 此外,您需要使您的Retrofit实例可用,以便为接收到的JSON错误响应应用适当的响应转换器。

public class ErrorUtils {

public static APIError parseError(Response> response) {

Converter converter =

ServiceGenerator.retrofit()

.responseBodyConverter(APIError.class, new Annotation[0]);

APIError error;

try {

error = converter.convert(response.errorBody());

} catch (IOException e) {

return new APIError();

}

return error;

}

}

首先将APIError类作为参数传递给responseBodyConverter方法,这个方法是retrofit中的方法。responseConverter方法将返回适当的转换器来解析响应体类型。

Error Handler inAction

在Retrofit 2中,所有可以执行(发送到API)并且接收到响应的请求都被视为“sucess”。这意味着,对于这些请求,onResponse回调被触发,您需要手动检查请求是否实际成功(状态200-299)或错误(状态400-599)。

如果请求成功完成,我们可以使用响应对象,并做任何我们想要的。 如果错误实际上失败(状态400-599),我们要向用户显示有关该问题的适当信息。

Call call = service.me();

call.enqueue(new Callback() {

@Override

public void onResponse(Call call, Response response) {

if (response.isSuccessful()) {

// use response data and do some fancy stuff :)

} else {

// parse the response body …

APIError error = ErrorUtils.parseError(response);

// … and use it to show error information

// … or just log the issue like we’re doing :)

Log.d("error message", error.message());

}

}

@Override

public void onFailure(Call call, Throwable t) {

// there is more than just a failing request (like: no internet connection)

}

});

这样就可以使用ErrorUtils类来处理错误了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值