Okhttp设置缓存

1.首先进行先进行设置:

[java]  view plain  copy
  1. private static final OkHttpClient client;  
  2.     private static final long cacheSize = 1024 * 1024 * 20;// 缓存文件最大限制大小20M  
  3.     private static String cacheDirectory = Environment.getExternalStorageDirectory() + "/okttpcaches"// 设置缓存文件路径  
  4.     private static Cache cache = new Cache(new File(cacheDirectory), cacheSize);  //  
  5.   
  6.     static {  
  7.         //如果无法生存缓存文件目录,检测权限使用已经加上,检测手机是否把文件读写权限禁止了  
  8.         OkHttpClient.Builder builder = new OkHttpClient.Builder();  
  9.         builder.connectTimeout(8, TimeUnit.SECONDS); // 设置连接超时时间  
  10.         builder.writeTimeout(8, TimeUnit.SECONDS);// 设置写入超时时间  
  11.         builder.readTimeout(8, TimeUnit.SECONDS);// 设置读取数据超时时间  
  12.         builder.retryOnConnectionFailure(true);// 设置进行连接失败重试  
  13.         builder.cache(cache);// 设置缓存  
  14.         client = builder.build();  
  15.   
  16.     }  




注意的是:okhttp只会对get请求进行缓存,post请求是不会进行缓存,这也是有道理的,因为get请求的数据一般是比较持久的,而post一般是交互操作,没太大意义进行缓存。


2.进行get请求:

一般来说的是,我们get请求有时有不一样的需求,有时需要进行缓存,有时需要直接从网络获取,有时只获取缓存数据,这些处理,okhttp都有帮我们做了,我们做的只需要设置就是了。下面是整理的各种需求的设置与使用方法。


  1.进行get请求,将数据缓存返回。(请求失败、无网络也返回缓存数据)

[java]  view plain  copy
  1. /** 如果没有缓存,进行get请求获取服务器数据并缓存起来 
  2.     * 如果缓存已经存在:不超过maxAge---->不进行请求,直接返回缓存数据 
  3.     *                    超出了maxAge--->发起请求获取数据更新,请求失败返回旧的缓存数据 
  4.     * @param url 
  5.     * @param cache_maxAge_inSeconds 
  6.     * @param responseListener 
  7.     * @return 
  8.     */  
  9.    public static Call DoGetAndCache(String url, int cache_maxAge_inSeconds,   
  10.                                     final NetWorkResponseListener responseListener) {  
  11.        Request request = new Request.Builder()  
  12.                .cacheControl(new CacheControl.Builder().maxAge(cache_maxAge_inSeconds, TimeUnit.SECONDS)  
  13.                        .build())  
  14.                .url(url).build();  
  15.   
  16.        Call call = client.newCall(request);  
  17.        startRequest(call, responseListener);  
  18.        return call;  
  19.    }  


2.进行get请求,将数据缓存返回,并指定缓存数据有效时间。

[java]  view plain  copy
  1. /** 如果没有缓存,进行get请求获取服务器数据并缓存起来 
  2.    * 如果缓存已经存在:不超过maxStale---->不进行请求,直接返回缓存数据 
  3.    *                    超出了maxStale--->发起请求获取数据更新,请求失败返回失败 
  4.    * @param url 
  5.    * @param cache_maxStale_inSeconds 
  6.    * @param responseListener 
  7.    * @return 
  8.    */  
  9.   public static Call DoGetAndCacheInStaleTime(String url, int cache_maxStale_inSeconds,  
  10.                                    final NetWorkResponseListener responseListener) {  
  11.       Request request = new Request.Builder()  
  12.               .cacheControl(new CacheControl.Builder().maxStale(cache_maxStale_inSeconds, TimeUnit.SECONDS)  
  13.                       .build())  
  14.               .url(url).build();  
  15.   
  16.       Call call = client.newCall(request);  
  17.       startRequest(call, responseListener);  
  18.       return call;  
  19.   }  

maxAge与maxStale的区别:

maxAge:没有超出maxAge,不管怎么样都是返回缓存数据,超过了maxAge,发起新的请求获取数据更新,请求失败返回缓存数据。

maxStale:没有超过maxStale,不管怎么样都返回缓存数据,超过了maxStale,发起请求获取更新数据,请求失败返回失败


  3.进行get请求,只使用网络数据

[java]  view plain  copy
  1. /** 
  2.      * get请求,只获取网络数据 
  3.      * 
  4.      * @param url 
  5.      * @param responseListener 
  6.      * @return 
  7.      */  
  8.     public static Call DoGetOnlyNet(String url, final NetWorkResponseListener responseListener) {  
  9.         Request request = new Request.Builder().cacheControl( CacheControl.FORCE_NETWORK).url(url)  
  10.                 .build();  
  11.         Call call = client.newCall(request);  
  12.         startRequest(call, responseListener);  
  13.         return call;  
  14.     }  


  4.get请求,只使用缓存数据

[java]  view plain  copy
  1. /** 
  2.    * get请求, 只使用缓存,注意,如果没有缓存数据,返回504,否则就返回缓存数据,不管缓存数据是否超出max-age与max-stale 
  3.    * 
  4.    * @param url 
  5.    * @param responseListener 
  6.    */  
  7.   public static Call DoGetOnlyCache(String url, final NetWorkResponseListener responseListener) {  
  8.       Request request = new Request.Builder().cacheControl( CacheControl.FORCE_CACHE).url(url)  
  9.               .build();  
  10.       Call call = client.newCall(request);  
  11.       startRequest(call, responseListener);  
  12.       return call;  
  13.   }  


startrequest(Call call0):

[java]  view plain  copy
  1. private static void startRequest(final Call call0,  
  2.                                      final NetWorkResponseListener responseListener) {  
  3.         try {  
  4.             call0.enqueue(new Callback() {  
  5.                 @Override  
  6.                 public void onFailure(Call arg0, IOException arg1) {  
  7.                     String message = "未知错误";  
  8.                     if (arg1 != null) {  
  9.                         Throwable t = arg1.getCause();  
  10.                         message = arg1.toString();  
  11.                         if (t != null) {  
  12.                             if (t instanceof SocketTimeoutException) {  
  13.                                 message = "请求超时了";  
  14.                             } else if (t instanceof UnknownHostException) {  
  15.                                 message = "UnknownHostException,无法访问该地址";  
  16.                             }  
  17.   
  18.                         }  
  19.                     }  
  20.   
  21.                     responseListener.onFail(message);  
  22.   
  23.                 }  
  24.   
  25.                 @Override  
  26.                 public void onResponse(Call arg0, Response response) throws IOException {  
  27.   
  28.                     if (response.isSuccessful()) {  
  29.                         responseListener.onSuccess(response.body().string() + "");  
  30.                     } else {  
  31.                         if(response.cacheResponse()!=null){  
  32.                             responseListener.onSuccess(response.cacheResponse().body().string() + "");  
  33.                         }else {  
  34.                             responseListener.onFail("response失败了,连接状态码为:" + response.code());  
  35.                         }  
  36.                     }  
  37.   
  38.   
  39.                 }  
  40.   
  41.             });  
  42.   
  43.         } catch (Exception e) {  
  44.             responseListener.onFail("请求异常:" + e.toString());  
  45.   
  46.         }  
  47.     }  

下面测试一下,设置缓存maxStale为10秒,我们将请求返回的数据打印出来:



     上面图片的1是点击获取的服务器的数据,获取后断开网络然后继续点击,可以看到2还能获取到数据,说明这是缓存的数据,当到3时,差不多就是十秒的时间,可以看到,获取数据失败了,这时已经去服务器获取数据了,由于断开网络所以请求失败。


可能出现的问题:


1.缓存文件没有生成。

只要配置成功,缓存目录一定会有的,所以看看:1.权限配置是否完整  2.手机应用权限是不是拒绝了。

[java]  view plain  copy
  1. <uses-permission android:name="android.permission.INTERNET"/>  
  2. <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>  
  3. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  

2.缓存没有生成,maxAge等配置了不起作用。

可能是请求的服务器不支持配置返回maxAge等头数据,建议通过配置缓存拦截器去添加这些参数:

[java]  view plain  copy
  1. static {    
  2.         //如果无法生存缓存文件目录,检测权限使用已经加上,检测手机是否把文件读写权限禁止了    
  3.         OkHttpClient.Builder builder = new OkHttpClient.Builder();    
  4.         builder.connectTimeout(8, TimeUnit.SECONDS); // 设置连接超时时间    
  5.         builder.writeTimeout(8, TimeUnit.SECONDS);// 设置写入超时时间    
  6.         builder.readTimeout(8, TimeUnit.SECONDS);// 设置读取数据超时时间    
  7.         builder.retryOnConnectionFailure(true);// 设置进行连接失败重试    
  8.         builder.cache(cache);// 设置缓存    
  9.         builder.addNetworkInterceptor(new CacheInterceptor());//缓存拦截器,通过这个设置maxAge与maxStale   
  10.         client = builder.build();    
  11.     
  12.     }    
  13.     
  14.     /**  
  15.      * 缓存拦截器  
  16.      */    
  17.     private static class CacheInterceptor implements Interceptor {    
  18.     
  19.         @Override    
  20.         public Response intercept(Chain chain) throws IOException {    
  21.     
  22.             Response originResponse = chain.proceed(chain.request());    
  23.     
  24.             //设置缓存时间为,并移除了pragma消息头,移除它的原因是因为pragma也是控制缓存的一个消息头属性    
  25.             return originResponse.newBuilder().removeHeader("pragma")    
  26.                     .header("Cache-Control""max-age=10")//设置10秒    
  27.                     .header("Cache-Control""max-stale=30").build();    
  28.         }    
  29.     }    


3.缓存返回总是返回504或者无法返回缓存数据,可是缓存文件又已经生成

如果get请求是带参数的话,可能参数值不同导致拼接的url地址不一样,会被认为是新地址去重新发起请求获取数据,当然被认为没有缓存数据


以上都是本人查看官方文档并进行测试验证后整理的,有不对的地方,万请指正。

封装了比较完整的网络请求工具类,包括请求相关信息的判断以及请求日志记录等,需要的可以看看:

点击进入

猜你喜欢

转载自blog.csdn.net/ltp_zy/article/details/79710363