当下 Android 应用最流行的网络框架莫过于 Okhttp 了,在使用的过程中,我们有各种各样的业务需求,比如打印请求日志、增加通用的请求参数、补充请求头参数、请求结果封装成统一的Bean类等等,那么拦截器就派上用场了!
什么是拦截器
引用官网的话就是:是一种 可以 管理,重写,重试请求调用的强大机制。
-
应用拦截器
-
网络拦截器
拦截器 是应用了 责任链模式,依次有序的调用,先调用应用级拦截器,再调用网络拦截器。
两者之间的区别: -
应用拦截器
1.不会去关心中间的响应,比如说重定向或重连。只能是第一次的请求和最终的响应结果
2.只会被调用 1 次,及时是来自缓存的响应
3.观察应用最原始的意图,不能操作 okhttp 为我们自动添加的请求头,比如 if-none-match
4.允许短路链接,可以不去调用 Chain.proceed()
5.允许 请求失败后重试 并且允许调用 Chain.proceed() -
网络拦截器
1.允许操作中间响应,比如重试或重定向
2.不允许使用缓存来达到 短路请求
3.可以观察 在网络中传输的数据
4.允许 通过 Connection 对象来装在 请求
拦截器的使用
1.打印日志
说到打印日志,Okhttp自己出了一个日志打印工具:HttpLoggingInterceptor,有四种打印模式:None、Basic、Headers、Body,顾名思义,我们已经能猜到四种模式的区别了。
接下来我们自己指定一个日志打印拦截器:
public class LoggingInterceptor implements Interceptor {
@NotNull
@Override
public Response intercept(@NotNull Chain chain) throws IOException {
Request request = chain.request(); //获取请求对象
//通过请求实例获取各种请求信息
HttpUrl httpUrl = request.url();//请求链接
RequestBody requestBody = request.body();//请求体
Headers headers = request.headers();//请求头
String requestMethod = request.method();//请求方法
for (int i = 0; i < headers.size(); i++) {
Log.d("interceptor", headers.name(i) + headers.value(i));
}
return chain.proceed(request);
}
}
private OkHttpClient createOkHttpClient() {
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
if (BuildConfig.DEBUG) {
httpLoggingInterceptor.level(HttpLoggingInterceptor.Level.BODY);
} else {
httpLoggingInterceptor.level(HttpLoggingInterceptor.Level.NONE);
}
mOkHttpClient = new OkHttpClient.Builder()
.addInterceptor(new LoggingInterceptor())
.addNetworkInterceptor(httpLoggingInterceptor)
.readTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.connectTimeout(15, TimeUnit.SECONDS)
.build();
return mOkHttpClient;
}
2.动态添加请求头 Headers
为了让服务器 识别是自己人在访问,有时候需要在请求头 中加上一些 识别的信息,我们不可能每个请求都手动添加一遍,只会在拦截器中统一添加。
public class HeadersInterceptor implements Interceptor {
@NotNull
@Override
public Response intercept(@NotNull Chain chain) throws IOException {
Request request = chain.request();
Headers headers = request.headers();
headers = new Headers.Builder().addAll(headers).
add("", "").
add("", "").
build();
request = request.newBuilder().headers(headers).build();
return chain.proceed(request);
}
}
3.添加统一参数
和添加统一的头信息一样,我们也需要添加统一的参数
扫描二维码关注公众号,回复:
8703248 查看本文章
public class ParameterInterceptor implements Interceptor {
@NotNull
@Override
public Response intercept(@NotNull Chain chain) throws IOException {
Request request = chain.request();
//1.对url 添加get参数
HttpUrl httpUrl = request.url().newBuilder().addEncodedQueryParameter("", "").build();
//2.对requestBody 添加 post参数
RequestBody requestBody = request.body();
if (null == requestBody) {
requestBody = new FormBody.Builder().addEncoded("", "").build();
} else if (requestBody instanceof FormBody) {
FormBody.Builder builder = new FormBody.Builder();
for (int i = 0; i < ((FormBody) requestBody).size(); i++) {
builder.add(((FormBody) requestBody).name(i), ((FormBody) requestBody).value(i));
}
builder.add("", "");
requestBody = builder.build();
}
//3.重新构造request
request = request.newBuilder().url(httpUrl).post(requestBody).build();
return chain.proceed(request);
}
}