Android Volley + JSONObjectRequest缓存是怎样的?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (47)
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);
    }
}

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

  1. 它会首先打开缓存并将其发送给响应
  2. 那么当结果通过远程服务器时,它会将它提供给响应者

更新:

我想如何手动检索缓存并将其重构为JSONObject并通过OnResponse函数发送,但考虑到存在隐式缓存,这看起来效率不高。JsonObjectRequest类应该返回JSONObject作为缓存条目而不是原始响应数据。

提问于
用户回答回答于

你可以做的是改变这个方法, com.android.volley.toolbox.HttpHeaderParser.parseCacheHeaders(NetworkResponse response) 并忽略这些头文件,设置entry.softTtlentry.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;
}

在你的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));
    }

}
用户回答回答于

关键是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));
        }
}

扫码关注云+社区