OkHttp 拦截器

当下 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.添加统一参数

和添加统一的头信息一样,我们也需要添加统一的参数

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);
    }
}
发布了6 篇原创文章 · 获赞 2 · 访问量 393

猜你喜欢

转载自blog.csdn.net/tocong2015/article/details/103802791
今日推荐