Android OKHttp3拦截器的使用方法

本文介绍了Android OKHttp3拦截器的使用方法,分享给大家,具体如下:

添加Interceptor

在上一篇中我们已经知道了okhttp的基本使用,其中在介绍OkHttpClient初始化的时候,介绍了两种方式,第二种方式就可以对这个OkHttpClient对象设置拦截器,如下所示:

// 配置一些信息进入OkHttpClient
mOkHttpClient = new OkHttpClient().newBuilder()
        .connectTimeout(REQUEST_TIME, TimeUnit.SECONDS)
        .readTimeout(REQUEST_TIME, TimeUnit.SECONDS)
        .writeTimeout(REQUEST_TIME, TimeUnit.SECONDS)
        .addInterceptor(new LoggerInterceptor())
        .build();

如上代码,很简单,只要利用addInterceptor方法就可以添加拦截器,而自定义的拦截器只需要实现 Interceptor 接口就行了,如下所示:

public class LoggerInterceptor implements Interceptor {
   ...
}

应用场景

日志打印

可以使用拦截器方便的打印网络请求时,需要查看的日志。如下所示:

public class LoggerInterceptor implements Interceptor {

  @Override
  public Response intercept(@NonNull Chain chain) throws IOException {
    // 拦截请求,获取到该次请求的request
    Request request = chain.request();
    // 执行本次网络请求操作,返回response信息
    Response response = chain.proceed(request);
    if (Configuration.DEBUG) {
      for (String key : request.headers().toMultimap().keySet()) {
        LogUtil.e("zp_test", "header: {" + key + " : " + request.headers().toMultimap().get(key) + "}");
      }
      LogUtil.e("zp_test", "url: " + request.url().uri().toString());
      ResponseBody responseBody = response.body();

      if (HttpHeaders.hasBody(response) && responseBody != null) {
        BufferedReader bufferedReader = new BufferedReader(new
            InputStreamReader(responseBody.byteStream(), "utf-8"));
        String result;
        while ((result = bufferedReader.readLine()) != null) {
          LogUtil.e("zp_test", "response: " + result);
        }
        // 测试代码
        responseBody.string();
      }
    }
    // 注意,这样写,等于重新创建Request,获取新的Response,避免在执行以上代码时,
    // 调用了responseBody.string()而不能在返回体中再次调用。
    return response.newBuilder().build();
  }

}

做了一个打印验证:通过分别打印拦截器与返回体的时间和线程名字,可以知道这两者处于同一线程中,增加拦截器,请求执行的时间也会增加,所以猜测,其实就是线性的在执行不同拦截器中的代码,根据需求返回一个相同的或者新的response。

缓存

想要实现缓存,先在创建okhttpclint的时候多加一行代码 .cache() ,通过它来设置缓存目录,当然需要服务器支持缓存功能。

mOkHttpClient = new OkHttpClient().newBuilder()
        .cache(new Cache(FileUtils.getCacheDirectory(AppApplication
            .getApplication(), ""), 1024 * 1024))
        .connectTimeout(REQUEST_TIME, TimeUnit.SECONDS)
        .readTimeout(REQUEST_TIME, TimeUnit.SECONDS)
        .writeTimeout(REQUEST_TIME, TimeUnit.SECONDS)
        .addNetworkInterceptor(new LoggerInterceptor())
        .build();

如果服务器端支持缓存的话,则请求所返回的Response会带有这样的头信息header:cache-control, max-age=xxx,这样设置。这时可以直接使用缓存功能。其中,max-age设置的缓存时间,过了这个时间,就算有缓存也不会进行使用。

像我公司服务器返回的头信息中与缓存相关的字段如下:

header: {cache-control : [no-store, private]}

header: {pragma : [no-cache]}

这就说明,服务器默认是不支持缓存的,okhttp就不会对此次请求进行缓存。

接下来再看拦截器中如何设置缓存

public class LoggerInterceptor implements Interceptor {

  @Override
  public Response intercept(@NonNull Chain chain) throws IOException {
    // 拦截请求,获取到该次请求的request
    Request request = chain.request();
    // 执行本次网络请求操作,返回response信息
    Response response = chain.proceed(request);
    if (Configuration.DEBUG) {
      for (String key : request.headers().toMultimap().keySet()) {
        LogUtil.e("zp_test", "header: {" + key + " : " + request.headers().toMultimap().get(key) + "}");
      }
      LogUtil.e("zp_test", "url: " + request.url().uri().toString());
      ResponseBody responseBody = response.body();
    }

    return response.newBuilder()
      // 增加一个缓存头信息,缓存时间为60s
      .header("cache-control", "public, max-age=60")
       // 移除pragma头信息
      .removeHeader("pragma")
      .build();
  }
}

这样设置,就等于是在60s内强制设置使用缓存。

注意点:

切记,最开始,我一直在犯一个错误,okhttp3不能缓存post接口

拦截器可以理解为,给请求的request和response重新一次封装的机会,使得你可以在特定条件下,给一些特定的接口或者满足特定条件的接口一些特殊的操作。

比如有一种场景,有网络时,进行请求,无网络时,拿缓存数据。

if (NetUtils.isNetAvailable(AppApplication.getApplication())) {
   response.newBuilder()
        .header("Cache-Control", "public, max-age=" + 0)
        .removeHeader("Pragma")
        .build();
 } else {
   int maxStale = 60 * 60 * 24; // 无网络时,设置超时为1天
   response.newBuilder()
       .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
       .removeHeader("Pragma")
       .build();
 } 

return response;

max-stale:在max-age指定的失效时间外,额外增加一段指定的时间可以使用失效的response。

网上有很多是上面这种做法,但是,我在拦截器中试了一下,当没有网络时,压根就不会走入拦截器。(我使用的是网络拦截器,如果有是别的什么原因,欢迎指出错误)

最终解决方案是在初始化request(如果初始化不熟悉可以参考我的上一篇文章OKHttp3的基本使用)的时候进行的判断操作,当有网络时初始化正常的request,当没有网络时初始化强制使用缓存的request:

Request request;
if (NetUtils.isNetAvailable(AppApplication.getApplication())) {
   request = addHeaderInfo().url(requestUrl).build();
} else {
   request = addHeaderInfo().url(requestUrl).cacheControl(CacheControl.FORCE_CACHE).build();
}

拦截器还是使用上面的那种形式,只是将有效时间变成了0

response.newBuilder()
       .header("Cache-Control", "public, max-age=" + 0)
       .removeHeader("Pragma")
       .build();

这样就可以在有网络的情况下使用最新的数据,在无网络的情况下使用缓存数据。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

您可能感兴趣的文章:

  • Android 封装Okhttp+Retrofit+RxJava,外加拦截器实例
  • Android 中okhttp自定义Interceptor(缓存拦截器)
  • Android的OkHttp包中的HTTP拦截器Interceptor用法示例
(0)

相关推荐

  • Android的OkHttp包中的HTTP拦截器Interceptor用法示例

    OkHttp(GitHub:https://github.com/square/okhttp) 的 Interceptor 就如同名称「拦截器」一样,拦截你的 Request 做一些你想做的事情再送出去.例如: 1.自动加上使用者目前使用的语言送出去取得对应语言的回传内容. 2.将 Request 计算出这个 Request 的 sigunature 再附加上送出去. 在 okHttp 中分成 Application Interceptor 和 Network Interceptor 两种. A

  • Android 封装Okhttp+Retrofit+RxJava,外加拦截器实例

    1.创建一个接口,用来定义接口使用的 public interface Api { @POST("product/getProductDetail") Observable<Goods_Bean> getGoods(@QueryMap Map<String,String> map); @POST("product/addCart") Observable<Add_Bean> getAdd(@QueryMap Map<Stri

  • Android 中okhttp自定义Interceptor(缓存拦截器)

    Android 中okhttp自定义Interceptor(缓存拦截器) 前言: 新公司项目是没有缓存的,我的天,坑用户流量不是么.不知道有人就喜欢一个界面没事点来点去的么.怎么办?一个字"加". 由于项目的网络请求被我换成了retrofit.而retrofit的网络请求默认基于okhttp okhttp的缓存由返回的header 来决定.如果服务器支持缓存的话返回的headers里面会有这一句 "Cache-Control","max-age=time&

  • Android OKHttp3拦截器的使用方法

    本文介绍了Android OKHttp3拦截器的使用方法,分享给大家,具体如下: 添加Interceptor 在上一篇中我们已经知道了okhttp的基本使用,其中在介绍OkHttpClient初始化的时候,介绍了两种方式,第二种方式就可以对这个OkHttpClient对象设置拦截器,如下所示: // 配置一些信息进入OkHttpClient mOkHttpClient = new OkHttpClient().newBuilder() .connectTimeout(REQUEST_TIME,

  • JavaWeb开发中alias拦截器的使用方法

    在SSH项目中,有时需要由一个Action跳转到另一个Action.有两种方式可以实现Action之间的跳转,一种是chain,另一种是redirectAction,这两种方式之间的区别是chain是在服务器上跳转,可以实现不同Action之间的数据共享:而redirectAction是在客户端进行跳转. 使用chain在不同的Action之间传递参数值,这个功能可以通过alias拦截器来实现. 1. 指定Filter类 在web.xml中设置下面的拦截器: <filter> <filt

  • vue中axios解决跨域问题和拦截器的使用方法

    vue中axios不支持vue.use()方式声明使用. 所以有两种方法可以解决这点: 第一种: 在main.js中引入axios,然后将其设置为vue原型链上的属性,这样在组件中就可以直接 this.axios使用了 import axios from 'axios'; Vue.prototype.axios=axios; components: this.axios({ url:"a.xxx", method:'post', data:{ id:3, name:'jack' } }

  • 简单总结SpringMVC拦截器的使用方法

    SpringMVC拦截器 拦截器类似于Filter过滤器,它是springMVC特有的,它可以预处理和后处理,我们可以定义一些拦截器来实现特定的业务. 过滤器与拦截器本质区别: (1)拦截器时AOP思想的具体应用(一个横切面,直接切进请求响应中去). (2)拦截器时spring MVC特有的. (3)拦截器只会拦截 访问控制器的方法,如果访问静态资源如:.jsp/html/css/image/js 时,它不会去拦截,而Filter过滤器无论什么都会去拦截. 自定义拦截器需要两步: 第一步:编写自

  • SpringBoot项目拦截器获取Post方法的请求body实现

    1). 存在问题流只能读取一次 2). 目标多次读取流 3). 解决方法创建包装类 4). RequestWrapper package com.mazaiting.redeye.wrapper;   import com.mazaiting.redeye.utils.StreamUtil; import lombok.extern.slf4j.Slf4j; import org.slf4j.Logger; import org.slf4j.LoggerFactory;   import jav

  • SpringBoot过滤器与拦截器深入分析实现方法

    目录 过滤器 编写过滤器 注册过滤器 基于 FilterRegistrationBean 基于 @WebFilter 拦截器 过滤器 实现过滤器需要实现 javax.servlet.Filter 接口.重写三个方法.其中 init() 方法在服务启动时执行,destroy() 在服务停止之前执行. 可用两种方式注册过滤器: 使用 FilterRegistrationBean 来注入.可使用 setOrder(0) 设置过滤器的优先级,越小优先级越高. 使用 @WebFilter(filterNa

  • Java的Struts框架中Action的编写与拦截器的使用方法

    Struts2 Action/动作 动作是Struts2框架的核心,因为他们的任何MVC(模型 - 视图 - 控制器)框架.每个URL将被映射到一个特定的动作,它提供了来自用户的请求提供服务所需的处理逻辑. 但动作也提供其他两个重要的能力.首先,操作从请求数据的传输中起着重要的作用,通过向视图,无论是一个JSP或其它类型的结果.二,动作必须协助的框架,在确定结果应该渲染视图,在响应该请求将被退回. 创建动作: 在Struts2的动作,唯一的要求是必须有一个无参数的方法返回String或结果的对象

  • vue中页面跳转拦截器的实现方法

    本文主要给大家介绍的是关于vue页面跳转拦截器的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍: 登录拦截逻辑 第一步:路由拦截 首先在定义路由的时候就需要多添加一个自定义字段requireAuth,用于判断该路由的访问是否需要登录.如果用户已经登录,则顺利进入路由, 否则就进入登录页面.在路由管理页面添加meta字段 import Vue from 'vue' import Router from 'vue-router' Vue.use(Router) const r

  • spring自定义注解实现拦截器的实现方法

    类似用户权限的需求,有些操作需要登录,有些操作不需要,可以使用过滤器filter,但在此使用过滤器比较死板,如果用的话,就必须在配置文件里加上所有方法,而且 不好使用通配符.这里可以采用一种比较简单灵活的方式,是采用spring 的 methodInterceptor拦截器完成的,并且是基于注解的.大概是用法是这样的: @LoginRequired @RequestMapping(value = "/comment") public void comment(HttpServletRe

  • vue 请求拦截器的配置方法详解

    按如下步骤进行 1.request.js内容:http request请求拦截器和http response服务器响应拦截器配置 2.http.js内容:请求数据方式封装 3.utils.js内容:获取token,判断token是否存在 4.store文件: vuex 仓库配置 vuex 持久化 vuex 模板引用 5.接口的封装 目录 request.js内容 http request请求拦截器和http response服务器响应拦截器配置 // http request 请求拦截器,有to

随机推荐