Android Volley + JSONObjectRequest缓存

gaa*_*a87 49 android caching response request android-volley

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望这段代码足以让我得到隐式缓存的响应.我不确定它是否有效,因为我在发送请求时假设:

  1. 它会首先点击缓存并将其发送到响应

  2. 然后,当结果从远程服务器传来时,它会将其提供给响应

更新:

我想到了如何手动检索缓存并将其重建为JSONObject并通过OnResponse函数发送它,但考虑到隐式缓存,这似乎并不高效.JsonObjectRequest类应该返回JSONObject作为缓存条目而不是原始响应数据.

但我仍然有兴趣知道我是否犯了一些错误.

模糊性完全是由于缺乏文档,所以如果我遗漏了一些非常明显的东西,我会道歉.

Ole*_*mov 88

请参阅此答案 - 使用Google的Volley设置缓存的过期策略

这意味着Volley仅根据标题"Cache-Control"然后"Expires","maxAge"决定是否缓存响应.

您可以做的是更改此方法 com.android.volley.toolbox.HttpHeaderParser.parseCacheHeaders(NetworkResponse response) 并忽略这些标题,集合entry.softTtl和entry.ttl字段以适合您的任何值,并在请求类中使用您的方法.这是一个例子:

/**
 * 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;
}
Run Code Online (Sandbox Code Playgroud)

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

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));
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 是的,缓存不仅保存在内存中,还保存在磁盘上(有关详细信息,请参阅DiskBasedCache类).作为快速测试,加载一些数据,退出应用程序,关闭wifi或3g并再次输入您的应用程序.您还可以在mMaxCacheSizeInBytes字段中指定缓存大小. (3认同)
  • 是的,当我在应用程序中时它会缓存,但是当我退出应用程序并返回应用程序时,从缓存中获取返回null.因此,它是否存在于活动生命周期之间的问题. (2认同)
  • 我正在做同样但它没有清除缓存.到期时间为1分钟. (2认同)

小智 5

oleksandr_yefremov提供了很好的代码,可以帮助您处理Android Volley的缓存策略,特别是当REST API具有不正确的"缓存控制"标头或您只是想要更多控制您自己的应用缓存策略时.

关键是HttpHeaderParser.parseCacheHeaders(NetworkResponse response)).如果您想拥有自己的缓存策略.取而代之的是parseIgnoreCacheHeaders(NetworkResponse response)在相应的类.

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

@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));
        }
}
Run Code Online (Sandbox Code Playgroud)

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