HttpResponseCache 在 Android Lollipop 中不起作用
Posted
技术标签:
【中文标题】HttpResponseCache 在 Android Lollipop 中不起作用【英文标题】:HttpResponseCache not working in Android Lollipop 【发布时间】:2015-06-13 13:37:08 【问题描述】:我一直在我的应用程序中成功使用 HttpResponseCache,但是当我的手机更新到 Lollipop 时,我意识到 HttpResponseCache 现在永远不会被“命中”,总是做网络请求。我已经确认在 android 版本中,Lollipop 之前的版本仍然运行良好。 也许这是我做错了什么,并且随着新的 Android 更改出现了。
有人知道吗?
我的代码:
应用程序类,onCreate...
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
try
File httpCacheDir = new File(getApplicationContext().getCacheDir()
, "http");
long httpCacheSize = 10 * 1024 * 1024;
HttpResponseCache.install(httpCacheDir, httpCacheSize);
catch (IOException e)
Log.i(TAG, "HTTP response cache installation failed:" + e);
else
try
File httpCacheDir = new File(getCacheDir(), "http");
long httpCacheSize = 10 * 1024 * 1024;
Class.forName("android.net.http.HttpResponseCache")
.getMethod("install", File.class, long.class)
.invoke(null, httpCacheDir, httpCacheSize);
catch (Exception e)
Log.i(TAG, "HTTP response cache installation failed:" +
管理请求的功能
public static InputStream fetchInputStream(String strURL, boolean forceRefresh)
throws IOException
HttpURLConnection mHttpConn = null;
InputStream inputStream = null;
URL url = new URL(strURL);
HttpResponseCache cache;
try
mHttpConn = (HttpURLConnection) url.openConnection();
if (forceRefresh)
mHttpConn.addRequestProperty("Cache-Control", "no-cache");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
cache = HttpResponseCache.getInstalled();
if (cache != null)
Log.i("TEST CACHE", "TEST PETICION: Req count: "
+ cache.getRequestCount() + ", hit count "
+ cache.getHitCount() + ", netWork count "
+ cache.getNetworkCount() + " size = "
+ cache.size() + " <-----------------");
mHttpConn.setUseCaches(true);
mHttpConn.setDefaultUseCaches(true);
mHttpConn.setRequestMethod("GET");
mHttpConn.setConnectTimeout(30000);
mHttpConn.setReadTimeout(30000);
mHttpConn.connect();
if (mHttpConn.getResponseCode() == HttpURLConnection.HTTP_OK)
inputStream = mHttpConn.getInputStream();
catch (IOException ex)
Log.e("NetworkConnectionManager InputStream", "Exception opening ["
+ strURL + "] ->", ex);
mHttpConn.disconnect();
throw ex;
return inputStream;
每次请求后
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
HttpResponseCache cache = HttpResponseCache.getInstalled();
if (cache != null)
cache.flush();
示例请求标头:
缓存控制 → max-age=300 连接 → 保持活动状态 内容编码 → gzip 内容类型 → 应用程序/json; charset=utf-8 日期 → 2015 年 4 月 8 日星期三 12:37:35 GMT 过期 → 2015 年 4 月 8 日星期三 12:42:35 GMT 最后修改时间 → 2015 年 4 月 8 日,星期三 12:37:35 GMT 服务器 → nginx 传输编码 → 分块 变化 → 接受编码 X 缓存 → 未命中【问题讨论】:
嘿查莫罗,check this out。它基本上说,如果您的清单中没有WRITE_EXTERNAL_STORAGE
权限,则可能存在一个会使您的缓存填充失败的错误。也许您可以添加它,只是为了检查这是否是您在这里遇到的问题。
这个问题在 Lollipop 中没有得到解决。任何人都可以在这里帮助我解决这个问题。我希望这可能是解决问题的任何技巧。
【参考方案1】:
在遇到这个问题几天后,我遇到了这个问题。它在 Marshmallow 中再次被修复。
这是棒棒糖中的一个错误,其中 Vary -> Accept-Encoding 标头会破坏缓存,因为 Accept-Encoding 在默认情况下会被填充但不会被写掉。
这里是问题的链接:
https://code.google.com/p/android/issues/detail?id=162475
解决方法是显式设置 Accept-Encoding:
接受编码 -> gzip
或
接受编码 -> 身份
在阅读方面,您必须将其添加到输入流的阅读中:
String encoding = urlConnection.getHeaderField("Content-Encoding");
boolean gzipped = encoding!=null && encoding.toLowerCase().contains("gzip");
Inputstream inputStream;
if(gzipped)
inputStream = new GZIPInputStream(urlConnection.getInputStream());
else
inputstream = urlConnection.getInputStream();
【讨论】:
这对我不起作用。有没有其他解决方案? @stevehs17 你对解决这个问题有什么建议吗? @iDroidExplorer:我已经有一段时间没有做这个了,但我记得我放弃了使用 HttpResponseCache 的整个想法,因为它在不同的 Android 操作系统版本中不能一致地工作。跨度> 【参考方案2】:我也遇到过类似的问题。我原以为图像会被缓存,但事实并非如此。
问题出在我没有关闭 InputStream
被读入位图后。
您的 fetchInputStream
返回一个从 http 连接获得的 InputStream,请确保正确关闭它。
在您关闭连接的InputStream
之前,android http 缓存不会保存资源。
【讨论】:
以上是关于HttpResponseCache 在 Android Lollipop 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Android 上使用 HttpsURLConnection 和 HttpResponseCache 强制缓存?
java.lang.NoClassDefFoundError 与 HttpResponseCache 和 DiskLruCache