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 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

如何使用已安装的 HttpResponseCache

如何在 Android 上使用 HttpsURLConnection 和 HttpResponseCache 强制缓存?

HttpResponseCache 不清除旧文件?

使用 HttpResponseCache 会使应用程序崩溃

java.lang.NoClassDefFoundError 与 HttpResponseCache 和 DiskLruCache

Android HttpResponseCache 不工作 - FileNotFoundException