1.首先进行先进行设置:
- private static final OkHttpClient client;
- private static final long cacheSize = 1024 * 1024 * 20;// 缓存文件最大限制大小20M
- private static String cacheDirectory = Environment.getExternalStorageDirectory() + "/okttpcaches"; // 设置缓存文件路径
- private static Cache cache = new Cache(new File(cacheDirectory), cacheSize); //
- static {
- //如果无法生存缓存文件目录,检测权限使用已经加上,检测手机是否把文件读写权限禁止了
- OkHttpClient.Builder builder = new OkHttpClient.Builder();
- builder.connectTimeout(8, TimeUnit.SECONDS); // 设置连接超时时间
- builder.writeTimeout(8, TimeUnit.SECONDS);// 设置写入超时时间
- builder.readTimeout(8, TimeUnit.SECONDS);// 设置读取数据超时时间
- builder.retryOnConnectionFailure(true);// 设置进行连接失败重试
- builder.cache(cache);// 设置缓存
- client = builder.build();
- }
注意的是:okhttp只会对get请求进行缓存,post请求是不会进行缓存,这也是有道理的,因为get请求的数据一般是比较持久的,而post一般是交互操作,没太大意义进行缓存。
2.进行get请求:
一般来说的是,我们get请求有时有不一样的需求,有时需要进行缓存,有时需要直接从网络获取,有时只获取缓存数据,这些处理,okhttp都有帮我们做了,我们做的只需要设置就是了。下面是整理的各种需求的设置与使用方法。
1.进行get请求,将数据缓存返回。(请求失败、无网络也返回缓存数据)。
- /** 如果没有缓存,进行get请求获取服务器数据并缓存起来
- * 如果缓存已经存在:不超过maxAge---->不进行请求,直接返回缓存数据
- * 超出了maxAge--->发起请求获取数据更新,请求失败返回旧的缓存数据
- * @param url
- * @param cache_maxAge_inSeconds
- * @param responseListener
- * @return
- */
- public static Call DoGetAndCache(String url, int cache_maxAge_inSeconds,
- final NetWorkResponseListener responseListener) {
- Request request = new Request.Builder()
- .cacheControl(new CacheControl.Builder().maxAge(cache_maxAge_inSeconds, TimeUnit.SECONDS)
- .build())
- .url(url).build();
- Call call = client.newCall(request);
- startRequest(call, responseListener);
- return call;
- }
- /** 如果没有缓存,进行get请求获取服务器数据并缓存起来
- * 如果缓存已经存在:不超过maxStale---->不进行请求,直接返回缓存数据
- * 超出了maxStale--->发起请求获取数据更新,请求失败返回失败
- * @param url
- * @param cache_maxStale_inSeconds
- * @param responseListener
- * @return
- */
- public static Call DoGetAndCacheInStaleTime(String url, int cache_maxStale_inSeconds,
- final NetWorkResponseListener responseListener) {
- Request request = new Request.Builder()
- .cacheControl(new CacheControl.Builder().maxStale(cache_maxStale_inSeconds, TimeUnit.SECONDS)
- .build())
- .url(url).build();
- Call call = client.newCall(request);
- startRequest(call, responseListener);
- return call;
- }
maxAge与maxStale的区别:
maxAge:没有超出maxAge,不管怎么样都是返回缓存数据,超过了maxAge,发起新的请求获取数据更新,请求失败返回缓存数据。
maxStale:没有超过maxStale,不管怎么样都返回缓存数据,超过了maxStale,发起请求获取更新数据,请求失败返回失败
3.进行get请求,只使用网络数据
- /**
- * get请求,只获取网络数据
- *
- * @param url
- * @param responseListener
- * @return
- */
- public static Call DoGetOnlyNet(String url, final NetWorkResponseListener responseListener) {
- Request request = new Request.Builder().cacheControl( CacheControl.FORCE_NETWORK).url(url)
- .build();
- Call call = client.newCall(request);
- startRequest(call, responseListener);
- return call;
- }
4.get请求,只使用缓存数据
- /**
- * get请求, 只使用缓存,注意,如果没有缓存数据,返回504,否则就返回缓存数据,不管缓存数据是否超出max-age与max-stale
- *
- * @param url
- * @param responseListener
- */
- public static Call DoGetOnlyCache(String url, final NetWorkResponseListener responseListener) {
- Request request = new Request.Builder().cacheControl( CacheControl.FORCE_CACHE).url(url)
- .build();
- Call call = client.newCall(request);
- startRequest(call, responseListener);
- return call;
- }
startrequest(Call call0):
- private static void startRequest(final Call call0,
- final NetWorkResponseListener responseListener) {
- try {
- call0.enqueue(new Callback() {
- @Override
- public void onFailure(Call arg0, IOException arg1) {
- String message = "未知错误";
- if (arg1 != null) {
- Throwable t = arg1.getCause();
- message = arg1.toString();
- if (t != null) {
- if (t instanceof SocketTimeoutException) {
- message = "请求超时了";
- } else if (t instanceof UnknownHostException) {
- message = "UnknownHostException,无法访问该地址";
- }
- }
- }
- responseListener.onFail(message);
- }
- @Override
- public void onResponse(Call arg0, Response response) throws IOException {
- if (response.isSuccessful()) {
- responseListener.onSuccess(response.body().string() + "");
- } else {
- if(response.cacheResponse()!=null){
- responseListener.onSuccess(response.cacheResponse().body().string() + "");
- }else {
- responseListener.onFail("response失败了,连接状态码为:" + response.code());
- }
- }
- }
- });
- } catch (Exception e) {
- responseListener.onFail("请求异常:" + e.toString());
- }
- }
下面测试一下,设置缓存maxStale为10秒,我们将请求返回的数据打印出来:
上面图片的1是点击获取的服务器的数据,获取后断开网络然后继续点击,可以看到2还能获取到数据,说明这是缓存的数据,当到3时,差不多就是十秒的时间,可以看到,获取数据失败了,这时已经去服务器获取数据了,由于断开网络所以请求失败。
可能出现的问题:
1.缓存文件没有生成。
只要配置成功,缓存目录一定会有的,所以看看:1.权限配置是否完整 2.手机应用权限是不是拒绝了。
- <uses-permission android:name="android.permission.INTERNET"/>
- <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
2.缓存没有生成,maxAge等配置了不起作用。
可能是请求的服务器不支持配置返回maxAge等头数据,建议通过配置缓存拦截器去添加这些参数:
- static {
- //如果无法生存缓存文件目录,检测权限使用已经加上,检测手机是否把文件读写权限禁止了
- OkHttpClient.Builder builder = new OkHttpClient.Builder();
- builder.connectTimeout(8, TimeUnit.SECONDS); // 设置连接超时时间
- builder.writeTimeout(8, TimeUnit.SECONDS);// 设置写入超时时间
- builder.readTimeout(8, TimeUnit.SECONDS);// 设置读取数据超时时间
- builder.retryOnConnectionFailure(true);// 设置进行连接失败重试
- builder.cache(cache);// 设置缓存
- builder.addNetworkInterceptor(new CacheInterceptor());//缓存拦截器,通过这个设置maxAge与maxStale
- client = builder.build();
- }
- /**
- * 缓存拦截器
- */
- private static class CacheInterceptor implements Interceptor {
- @Override
- public Response intercept(Chain chain) throws IOException {
- Response originResponse = chain.proceed(chain.request());
- //设置缓存时间为,并移除了pragma消息头,移除它的原因是因为pragma也是控制缓存的一个消息头属性
- return originResponse.newBuilder().removeHeader("pragma")
- .header("Cache-Control", "max-age=10")//设置10秒
- .header("Cache-Control", "max-stale=30").build();
- }
- }
3.缓存返回总是返回504或者无法返回缓存数据,可是缓存文件又已经生成
如果get请求是带参数的话,可能参数值不同导致拼接的url地址不一样,会被认为是新地址去重新发起请求获取数据,当然被认为没有缓存数据
以上都是本人查看官方文档并进行测试验证后整理的,有不对的地方,万请指正。
封装了比较完整的网络请求工具类,包括请求相关信息的判断以及请求日志记录等,需要的可以看看: