首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Android Volley + JSONObjectRequest缓存

Android Volley + JSONObjectRequest缓存
EN

Stack Overflow用户
提问于 2013-05-28 06:18:24
回答 4查看 46.5K关注 0票数 50
代码语言:javascript
复制
public class CustomRequest extends JsonObjectRequest {

    public CustomRequest(String url, JSONObject params,
            Listener<JSONObject> listener, ErrorListener errorListener)
            throws JSONException {
        super(Method.POST,url, params, listener,
                errorListener);
        this.setShouldCache(Boolean.TRUE);
    }
}

我希望这段代码足以让我获得响应的隐式缓存。我不确定它是否工作,因为当发送请求时,我是在假设下进行的:

当结果从远程服务器传来时,它将首先命中缓存并将其发送到onresponse

  • then,然后再将其提供给

更新:

我知道如何手动检索缓存并将其重构为JSONObject,然后通过OnResponse函数发送它,但考虑到存在隐式缓存,这似乎并不有效。JsonObjectRequest类应该返回JSONObject作为缓存条目,而不是原始响应数据。

但我还是有兴趣知道我是不是做错了什么。

这种含糊不清完全是由于缺乏文档,所以如果我遗漏了一些非常明显的东西,我道歉。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-05-31 15:46:53

查看此答案- Set expiration policy for cache using Google's Volley

这意味着Volley只根据" cache -Control“和"Expires”、"maxAge“来决定是否缓存响应。

您可以做的是更改此方法com.android.volley.toolbox.HttpHeaderParser.parseCacheHeaders(NetworkResponse response)并忽略这些头文件,将entry.softTtlentry.ttl字段设置为适合您的任何值,并在请求类中使用您的方法。下面是一个示例:

代码语言:javascript
复制
/**
 * Extracts a {@link Cache.Entry} from a {@link NetworkResponse}.
 * Cache-control headers are ignored. SoftTtl == 3 mins, ttl == 24 hours.
 * @param response The network response to parse headers from
 * @return a cache entry for the given response, or null if the response is not cacheable.
 */
public static Cache.Entry parseIgnoreCacheHeaders(NetworkResponse response) {
    long now = System.currentTimeMillis();

    Map<String, String> headers = response.headers;
    long serverDate = 0;
    String serverEtag = null;
    String headerValue;

    headerValue = headers.get("Date");
    if (headerValue != null) {
        serverDate = HttpHeaderParser.parseDateAsEpoch(headerValue);
    }

    serverEtag = headers.get("ETag");

    final long cacheHitButRefreshed = 3 * 60 * 1000; // in 3 minutes cache will be hit, but also refreshed on background
    final long cacheExpired = 24 * 60 * 60 * 1000; // in 24 hours this cache entry expires completely
    final long softExpire = now + cacheHitButRefreshed;
    final long ttl = now + cacheExpired;

    Cache.Entry entry = new Cache.Entry();
    entry.data = response.data;
    entry.etag = serverEtag;
    entry.softTtl = softExpire;
    entry.ttl = ttl;
    entry.serverDate = serverDate;
    entry.responseHeaders = headers;

    return entry;
}

在请求类中使用此方法,如下所示:

代码语言:javascript
复制
public class MyRequest extends com.android.volley.Request<MyResponse> {

    ...

    @Override
    protected Response<MyResponse> parseNetworkResponse(NetworkResponse response) {
        String jsonString = new String(response.data);
        MyResponse MyResponse = gson.fromJson(jsonString, MyResponse.class);
        return Response.success(MyResponse, HttpHeaderParser.parseIgnoreCacheHeaders(response));
    }

}
票数 89
EN

Stack Overflow用户

发布于 2013-10-12 05:00:49

oleksandr_yefremov提供了很棒的代码,可以帮助你处理安卓截击的缓存策略,特别是当REST API有不正确的cache - control头部时,或者你只是想更多地控制自己的应用缓存策略。

关键是HttpHeaderParser.parseCacheHeaders(NetworkResponse response))。如果你想拥有自己的缓存策略。将其替换为对应类中的parseIgnoreCacheHeaders(NetworkResponse response)

如果您的类扩展了JsonObjectRequest,请转到JsonObjectRequest并查找

代码语言:javascript
复制
@Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
    try {
            String jsonString =new String(response.data, HttpHeaderParser.parseCharset(response.headers));
            return Response.success(new JSONObject(jsonString),HttpHeaderParser.parseCacheHeaders(response));
        }catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        }catch (JSONException je) {
            return Response.error(new ParseError(je));
        }
}

并用HttpHeaderParser.parseIgnoreCacheHeaders替换HttpHeaderParser.parseCacheHeaders(response)

票数 5
EN

Stack Overflow用户

发布于 2014-09-19 03:53:49

+1也适用于oleksandr_yefremov和skyfishjy,并在这里提供了一个具体的、可重用的类,适用于json或其他基于字符串的API:

代码语言:javascript
复制
public class CachingStringRequest extends StringRequest {
    public CachingStringRequest(int method, String url, Response.Listener<String> listener, Response.ErrorListener errorListener) {
        super(method, url, listener, errorListener);
    }

    public CachingStringRequest(String url, Response.Listener<String> listener, Response.ErrorListener errorListener) {
        super(url, listener, errorListener);
    }

    @Override
    protected Response<String> parseNetworkResponse(NetworkResponse response) {
        String parsed;
        try {
            parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
        } catch (UnsupportedEncodingException e) {
            parsed = new String(response.data);
        }
        return Response.success(parsed, parseIgnoreCacheHeaders(response));
    }
}

其中函数parseIgnoreCacheHeaders()来自上面的oleksandr_yefremov答案。在生成的json可以缓存3分钟(实时)和24小时(过期但仍然可用)的任何地方使用CachingStringRequest类。示例请求:

代码语言:javascript
复制
CachingStringRequest stringRequest = new CachingStringRequest(MY_API_URL, callback);

在回调对象的onResponse()函数中,解析json。设置您想要的任何缓存限制--您可以对每个请求进行参数化,以添加自定义过期。

为了好玩,可以在一个简单的应用程序中尝试一下,该应用程序下载json并呈现下载的信息。用第一次成功的下载填充缓存后,在缓存处于活动状态时更改方向时,请观察快速渲染(如果实时缓存命中,则不会发生下载)。现在关闭应用程序,等待3分钟,等待缓存命中过期(但不是24小时,将其从缓存中删除),启用飞行模式,然后重新启动应用程序。将发生截击错误回调,并且将从缓存的数据中执行“成功的”onResponse()回调,从而允许您的应用程序既呈现内容,又知道/警告它来自过期的缓存。

这种缓存的一种用途是避免Loaders和其他处理方向变化的方法。如果请求通过Volley singleton,并且结果被缓存,则通过方向更改发生的刷新将从缓存中快速呈现,由Volley自动呈现,而无需Loader。

当然,这并不能满足所有需求。YMMV

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16781244

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档