安卓Http客户端缓存

6
在我的安卓应用程序中,我正在尝试缓存Http Client的响应。我使用Facebook Graph API进行此任务的测试,并具有以下网址:https://graph.facebook.com/riz.ahmed.52 首次获取“first_name”并显示它。然后更改我的Facebook个人资料的名字并再次调用相同的链接。我期望得到旧/已缓存的“first_name”,但我得到了更新后的结果。每当我调用该URL时,控制台始终显示“响应来自上游服务器”消息。
我的Http Client代码如下:
    CacheConfig cacheConfig = new CacheConfig();  
    cacheConfig.setMaxCacheEntries(1000);
    cacheConfig.setMaxObjectSizeBytes(8192);

    //HttpClient httpclient = new CachingHttpClient(new DefaultHttpClient(), cacheConfig);
    DefaultHttpClient httpclient = new DefaultHttpClient();
    HttpContext localContext = new BasicHttpContext();

    // Updated code [START]
    httpclient.addResponseInterceptor(new HttpResponseInterceptor() {
        public void process(
            final HttpResponse response,
            final HttpContext context) throws HttpException, IOException {

                 response.removeHeader(response.getFirstHeader("Pragma"));
                 response.removeHeader(response.getFirstHeader("Expires"));

            }                
        });
    // Updated code [END]

    HttpGet httpget = new HttpGet(url);

            // Execute HTTP Get Request
    HttpResponse response = httpclient.execute(httpget, localContext);
    HttpEntity entity = response.getEntity();
    String res = EntityUtils.getContentCharSet(entity);

    CacheResponseStatus responseStatus = (CacheResponseStatus) localContext.getAttribute(
        CachingHttpClient.CACHE_RESPONSE_STATUS);

    switch (responseStatus) {
        case CACHE_HIT:
            System.out.println("A response was generated from the cache with no requests " +
                "sent upstream");
            break;
        case CACHE_MODULE_RESPONSE:
                System.out.println("The response was generated directly by the caching module");
                break;
        case CACHE_MISS:
                System.out.println("The response came from an upstream server");
                break;
        case VALIDATED:
                System.out.println("The response was generated from the cache after validating " +
                        "the entry with the origin server");
                break;
            }

我正在使用 Android 2.3.3。请告诉我我错过了什么。
1个回答

4
您正在加载的页面指定了一个 Expires:Sat, 01 Jan 2000 00:00:00 GMT 头部,也就是说它总是被认为是过时的,并且必须重新获取。此外,似乎还返回了一个Pragma: no-cache。基本上,它告诉您的HTTP客户端永远不要缓存此页面。如果您一定要缓存响应,则可以使用HttpResponseInterceptor删除这些标头。使用 http-clientcache-4.2.jar 会有问题,因为它与Android SDK打包的HTTP客户端版本不完全兼容。当使用它时,您将获得 NoClassDefFoundError 和类似的无意义错误。但是,如果您通过下载clientcache-4.2的源代码并剥离任何未满足的引用(例如重构commons logging的包名称)并消除代码中散布的所有注释(等等),您可能会得到一个可工作的版本。如果您这样做,那么这个方法是有效的:
class MakeCacheable implements HttpResponseInterceptor {
    public static MakeCacheable INSTANCE = new MakeCacheable();
    public void process(HttpResponse resp, HttpContext ctx) throws HttpException, IOException {
        resp.removeHeaders("Expires");
        resp.removeHeaders("Pragma");
        resp.removeHeaders("Cache-Control");
    }
}

将以下内容注入到CachingHttpClient所使用的DefaultHttpClient中:

DefaultHttpClient realClient = new DefaultHttpClient();
realClient.addResponseInterceptor(MakeCacheable.INSTANCE, 0); // This goes first
CachingHttpClient httpClient = new CachingHttpClient(realClient, cacheConfig);

一个条目是否被缓存是由ResponseCachingPolicy决定的。不幸的是,它在CachingHttpClient中是一个final,但是查看它将显示所有需要执行的标题,以使不可缓存的条目变得可缓存。


我已经从响应中删除了两个头部,但结果仍然相同。 - rizzz86
你是怎么移除它们的?如果你通过更改HttpResponse response = httpclient.execute(httpget, localContext);返回的结果来做,那么你可能太晚了,无法使其正常工作。 - Jens
我通过添加响应拦截器来移除它。我已经更新了我的帖子,展示了我如何调用拦截器。 - rizzz86
我正在将一个外部库(apache http-clientcache-4.2.jar)添加到我的Android项目中。我将尝试将我的Android项目的目标设置为4.0.3并查看它的工作情况。 - rizzz86
@rizzz86 你有没有在这方面有过什么好运? - brk3
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接