我们学习了Retrofit的基本使用后,我们知道Retrofit内部其实还是由Okhttp实现的,Retrofit只是对其进行了一层封装,下面我们队Retrofit使用中常见的问题进行整理。
![](https://img.haomeiwen.com/i7756923/898f05905b8e933b.png)
Retrofit的扩展使用
一、拦截器
拦截器是一种强大的机制,可以监视,重写和重试调用,记录传出请求和传入响应,即可以实现网络监听、请求以及响应重写、请求失败重试等功能。
引用官网的一张图,下图标出了Application Interceptor和Network Interceptor两种拦截器,一般我们需要对Request或Response进行操作就是通过这两类拦截器来完成的。
![](https://img.haomeiwen.com/i7756923/fed4656e3077eae3.png)
拦截器可以以application
或者network
两种方式注册,可以调用addInterceptor()
以及addNetworkInterceptor
方法进行注册,我们对这些进行简单的学习。
addInterceptor() :
- 无法操作中间的响应,只能操作第一次请求以及返回的最终结果
- 监听请求的最原始意图(请求头,请求体等),无法操作OkHttp为我们自动添加的额外的请求头
- 总是只调用一次,即使HTTP响应是从缓存中获取
- 如果本地有缓存,可以从本地缓存中获取响应实例返回给客户端。
addNetworkInterceptor() :
- 能够详尽的追踪访问链接的重定向
- 短时间内的网络访问,它将不执行缓存过来的回应
- 监测整个网络过程的数据流量
- 当网络短路而返回缓存响应时不被调用
- 携带请求来访问连接
- 能从缓存池中获取缓存对象返回给客户端,通过请求服务的方式获取响应(
Chain.proceed()
)
二、基本使用,输出日志
我们在开发的应用经常是需要与网络互连进行交互的,但是我们怎么准确的输出我们请求的信息?Okhttp为我们提供了logging-interceptor
方便我们输出对应的日志信息github-khttp-logging-interceptor。
1、添加依赖
implementation 'com.squareup.okhttp3:logging-interceptor:3.11.0'
2、设置日志级别
-
HttpLoggingInterceptor.Level.HEADERS
// 开启请求头 -
HttpLoggingInterceptor.Level.BODY
//开启body日志 -
HttpLoggingInterceptor.Level.BASIC
//基础输出 HttpLoggingInterceptor.Level.NONE
添加网络拦截器
//基础输出
OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(new HttpLoggingInterceptor()
.setLevel(HttpLoggingInterceptor.Level.BASIC))
.build();
添加应用拦截器
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new HttpLoggingInterceptor()
.setLevel(HttpLoggingInterceptor.Level.BASIC))
.build();
3、使用方法
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("url")
.client(client)
.build();
三、增加统一的header
我们通过在请求网络的接口中设置header只对当前的定义的请求方法有效,而不对所有请求有效,因此我们通过设置统一的Header方便调用
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request=new Request.Builder()
.addHeader("key","value")
.addHeader("key","value")
.build();
return chain.proceed(request);
}
})
.build();
//使用通过client方法调用,与上面相同
四、设置Cookie
//记录下正确姿势
OkHttpClient client = new OkHttpClient.Builder()
.cookieJar(new CookieJar() {
private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
//Tip:這裡key必須是String
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
//可以持久化保存至本地
cookieStore.put(url.host(), cookies);
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
List<Cookie> cookies = cookieStore.get(url.host());
return cookies != null ? cookies : new ArrayList<Cookie>();
}
})
.build();
//使用与之前一致
五、设置缓存Cache
通过判断是否有网络,判断缓存时间
public class CacheInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (!NetworkUtils.isNetworkConnected(App.getInstance())) {
request = request.newBuilder()
.cacheControl(CacheControl.FORCE_CACHE)
.build();
}
Response response = chain.proceed(request);
if (NetworkUtils.isNetworkConnected(App.getInstance())) {
int maxAge = 60 * 60 * 24 ;
// 有网络时, 不缓存, 最大保存时长为1小时
response.newBuilder()
.header("Cache-Control", "public, max-age=" + maxAge)
.removeHeader("Pragma")
.build();
} else {
// 无网络时,设置超时为4周
int maxStale = 60 * 60 * 24 * 28;
response.newBuilder()
.header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
.removeHeader("Pragma")
.build();
}
return response;
}
}
使用
Interceptor cacheInterceptor = new CacheInterceptor();
OkHttpClient client= new OkHttpClient.Builder()
.addInterceptor(cacheInterceptor)
.build();
//使用与之前一致
网友评论