输出请求日志和响应日志
Retrofit在网络层完全依赖于OkHttp,有人为它做了一个日志拦截器来输出日志,首先在gradle中添加依赖:
1 | compile 'com.squareup.okhttp3:logging-interceptor:3.3.1' |
为OkHttp添加拦截器1
2
3
4
5
6
7
8
9
10
11
12
13
14
15HttpLoggingInterceptor 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); // <-- this is the important line!
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)。1
2D/HttpLoggingInterceptor$Logger: --> POST /upload HTTP/1.1 (277-byte body)
D/HttpLoggingInterceptor$Logger: <-- HTTP/1.1 200 OK (543ms, -1-byte body)
Headers
输出请求和响应的头信息(headers),请求类型(request type),请求地址(request url),响应码(response status)。
使用HEADERS日志级别只会记录请求和响应的头信息。Retrofit或OkHttp会默认添加相应的请求头,但它们不会显示在您的请求上,因为它们稍后会添加到请求链中。 如果自己添加请求头,请确保日志拦截器是添加到OkHttp客户端的最后一个拦截器。 如果您第一个添加拦截器,请求上尚未设置任何头数据。
我们使用两个头字段Accept和Content-Type来说明输出:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15D/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: <-- HTTP/1.1 200 OK (1039ms)
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: <-- END HTTP
除了服务器响应的头信息,还会输出选择协议的信息以及发送请求和接收响应时的相应毫秒数。
Body
输出请求和响应的头信息(headers)和内容(body)。
这是您将获得响应正文数据的唯一日志级别。 仅在必要时使用此级别。
1 | D/HttpLoggingInterceptor$Logger: --> POST /upload HTTP/1.1 |
只在开发环境下输出日志
自动化是增强开发人员关注点和生产力的最佳工具之一。启用和禁用Retrofit的日志记录可能是一个繁琐,重复的任务。所以让我们自动化这个过程:在开发过程中,将为调试版本启用日志记录; 并且您的应用程序的所有生产版本的日志记录将被禁用!
解决方案很简单:我们将使用由Android框架提供的BuildConfig.DEBUG布尔变量。 它将为您的开发环境返回true,对于您的生产环境返回false。
1 | OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); |
使用不同级别的日志
1 | OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); |
这样就可以在生产环境和正式环境中输出不同的日志了。
捕捉错误
在服务器发生错误或者用户输入的数据错误时,我们希望呈献给用户反馈信息,并要求他改正。
在这之前,我们来看一个简单的例子:
Error Object
首先我们创建一个错误json:
1 | { |
定义一个错误类
1 | public class APIError { |
Simple Error Handler
我们将使用下面的类,返回一个APIError对象的静态方法。 parseError方法的参数为Response。 此外,您需要使您的Retrofit实例可用,以便为接收到的JSON错误响应应用适当的响应转换器。
1 | public class ErrorUtils { |
首先将APIError类作为参数传递给responseBodyConverter方法,这个方法是retrofit中的方法。responseConverter方法将返回适当的转换器来解析响应体类型。
Error Handler inAction
在Retrofit 2中,所有可以执行(发送到API)并且接收到响应的请求都被视为“sucess”。这意味着,对于这些请求,onResponse回调被触发,您需要手动检查请求是否实际成功(状态200-299)或错误(状态400-599)。
如果请求成功完成,我们可以使用响应对象,并做任何我们想要的。 如果错误实际上失败(状态400-599),我们要向用户显示有关该问题的适当信息。
1 | Call<User> call = service.me(); |
这样就可以使用ErrorUtils类来处理错误了。