【问题标题】:Why Volley doesn't clear then update the cache when getting new data为什么 Volley 在获取新数据时不清除然后更新缓存
【发布时间】:2015-08-17 07:40:33
【问题描述】:

参考Setting Up a RequestQueue,我构建了一个带缓存的单例类示例,其中:

private RequestQueue getRequestQueue() {
    if (mRequestQueue == null) {            
        mRequestQueue = Volley.newRequestQueue(mContext.getApplicationContext(), 10 * 1024 * 1024);
    }
    return mRequestQueue;
}

在 MainActivity.java 中:

JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(0, mUrl, new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {                
            try {
                mTextView.setText(response.toString(5));
            } catch (JSONException e) {
                mTextView.setText(e.toString());
            }
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {                
        }
    }); 

我的情况:

服务器数据值为1234:

  • Wifi连接,运行Android应用,获取值:1234
  • Wifi断开,运行app,获取值:1234

服务器数据值更新为12345678:

  • Wifi连接,运行app,获取值:12345678

  • Wifi断开,运行app,获取值:1234

为什么 Volley 在从服务器获取新数据(与缓存数据不同的数据)时不清除然后更新缓存?如何强制?

【问题讨论】:

  • volley 如何知道服务器上的数据已更新?您需要明确告诉 volley 何时手动清除缓存或清除缓存
  • 我认为当它已经获得新数据(即 12345678)时,它会与缓存数据(1234)进行比较,因此它知道数据已更新。对吗?
  • 它没有获取新数据 - 它仍然有数据在缓存中,所以它不会进行网络调用。这就是缓存的全部意义所在。对吗?
  • 数据更新,wifi连上,新数据!
  • 好的,现在我很困惑...... Volley 要么从服务器获取新数据,要么使用缓存。 “我有新数据”是什么意思?

标签: android caching android-volley


【解决方案1】:

我发现mRequestQueue = Volley.newRequestQueue(mContext.getApplicationContext(), 10 * 1024 * 1024); 没有缓存的事实(我不知道这是否是一个答案)。

我的问题中的JsonObjectRequest 实际上获得了缓存,这是另一个具有相同 URL 的请求的结果。我会详细讲述(抱歉我的英语不好,可能不清楚):

在我的 Android 应用程序中,首先我创建一个 JsonObjectRequest,如下所示:

JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(0, mUrl, new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {
            try {
                mTextView.setText(response.toString(5));
            } catch (JSONException e) {
                mTextView.setText(e.toString());
            }
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {

        }
    }) {
        @Override
        protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
            try {
                Cache.Entry cacheEntry = HttpHeaderParser.parseCacheHeaders(response);
                if (cacheEntry == null) {
                    cacheEntry = new Cache.Entry();
                }
                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
                long now = System.currentTimeMillis();
                final long softExpire = now + cacheHitButRefreshed;
                final long ttl = now + cacheExpired;
                cacheEntry.data = response.data;
                cacheEntry.softTtl = softExpire;
                cacheEntry.ttl = ttl;
                String headerValue;
                headerValue = response.headers.get("Date");
                if (headerValue != null) {
                    cacheEntry.serverDate = HttpHeaderParser.parseDateAsEpoch(headerValue);
                }
                headerValue = response.headers.get("Last-Modified");
                if (headerValue != null) {
                    cacheEntry.lastModified = HttpHeaderParser.parseDateAsEpoch(headerValue);
                }
                cacheEntry.responseHeaders = response.headers;
                final String jsonString = new String(response.data,
                        HttpHeaderParser.parseCharset(response.headers));
                return Response.success(new JSONObject(jsonString), cacheEntry);
            } catch (UnsupportedEncodingException e) {
                return Response.error(new ParseError(e));
            } catch (JSONException e) {
                return Response.error(new ParseError(e));
            }
        }

        @Override
        protected void deliverResponse(JSONObject response) {
            super.deliverResponse(response);
        }

        @Override
        public void deliverError(VolleyError error) {
            super.deliverError(error);
        }

        @Override
        protected VolleyError parseNetworkError(VolleyError volleyError) {
            return super.parseNetworkError(volleyError);
        }
    };

    MySingleton.getInstance(this).addToRequestQueue(jsonObjectRequest);

此请求运行良好,缓存良好,刷新新数据(我访客 2-3 分钟后)

然后,我评论这个请求(名为请求 A)并创建另一个请求(我的问题中的那个,名为请求 B),重新运行 (Shift-F10) 我的 Android 应用程序,并得到我的问题中的问题.我认为 B 获得了 A 之前创建的缓存数据。

  • 如果 wifi 断开连接: 起初,只有 B 中的 onResponse 被调用,但 2-3 分钟后,onResponseonErrorResponse 都被调用(onResponseonErrorResponse 之前)。在第一次调用onErrorResponse 之后,当应用程序再次运行时,onErrorResponseonResponse 之后立即调用(不再是 2-3 分钟后)。 textView 显示缓存的数据(A 之前创建的)。

  • 如果 wifi 连接: 只有onResponse在B被调用,然而,起初textView显示缓存的数据(由A之前创建),不久之后,它显示了来自服务器的数据。我认为onResponse 打了两次电话。

然后,如果我从手机上卸载Android应用程序,再次运行应用程序(Shift-F10),B不再获取缓存数据。

【讨论】:

  • 我在模拟器而不是手机中遇到了这个问题。你找到解决办法了吗?
  • @serenei 所有的模拟器还是只有一个特定的?
  • 我只是在一个模拟器上测试..你是如何解决这个问题的?
  • @serenei 实际上,我根本没有修复任何东西,因为当时我只测试了 volley 的缓存。
猜你喜欢
  • 1970-01-01
  • 2019-09-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-03
  • 2012-09-21
  • 2022-01-27
  • 2016-08-03
  • 1970-01-01
相关资源
最近更新 更多