【问题标题】:Android: Volley does not work offline with cacheAndroid:Volley 无法使用缓存离线工作
【发布时间】:2014-09-04 11:44:09
【问题描述】:

我已经为获取 Json 对象的请求添加了 volley,如果 wifi 已打开,则它会获取数据但在离线模式的情况下不会获取,即使为请求启用了缓存。

我做下面的代码

public class VolleySingleton extends Application
{
    public static final String TAG = VolleySingleton.class.getSimpleName();
    private RequestQueue mRequestQueue;
    private static VolleySingleton mInstance;
    private ImageLoader mImageLoader;
    private final String DEFAULT_CACHE_DIR = "sl_cache";

    @Override
    public void onConfigurationChanged(Configuration newConfig)
    {
        super.onConfigurationChanged(newConfig);
    }

    @Override
    public void onCreate()
    {
        super.onCreate();
        mInstance = this;
    }

    public static synchronized VolleySingleton getInstance()
    {
        return mInstance;
    }

    public ImageLoader getImageLoader()
    {
        getRequestQueue();
        if (mImageLoader == null)
        {
            mImageLoader = new ImageLoader(this.mRequestQueue, new LruBitmapCache());
        }
        return this.mImageLoader;
    }

    public <T> void addToRequestQueue(Request<T> req, String tag)
    {
        // set the default tag if tag is empty
        req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
        getRequestQueue().add(req);
    }

    public <T> void addToRequestQueue(Request<T> req)
    {
        req.setTag(TAG);
        getRequestQueue().add(req);
    }

    public void cancelPendingRequests(Object tag)
    {
        if (mRequestQueue != null)
        {
            mRequestQueue.cancelAll(tag);
        }
    }

    public RequestQueue getRequestQueue()
    {
        if (mRequestQueue == null)
        {
            Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024 * 10); // 10MB cap
            Network network = new BasicNetwork(new HurlStack());
            mRequestQueue = new RequestQueue(cache, network);
            mRequestQueue.start();
        }
        return mRequestQueue;
    }
}


private void getData(String url, String tag)
{
            final JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>()
            {
                @Override
                public void onResponse(JSONObject response)
                {
                    Log.wtf("HOME", response.toString());
                    String result = parseData(response.toString());
                    postProcessing(result);
                    //SocialLadder.getInstance().getRequestQueue().getCache().invalidate(url, true);
                }


            }, new Response.ErrorListener()
            {
                @Override
                public void onErrorResponse(VolleyError error)
                {
                    VolleyLog.wtf("HOME", "Error: " + error.getMessage());
                    stopRefresher();
                }
            })
            {
                @Override
                protected Response<JSONObject> parseNetworkResponse(NetworkResponse response)
                {                        
                    try
                    {
                        String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
                        return !jsonString.isEmpty() ? Response.success(new JSONObject(jsonString), HttpHeaderParser.parseCacheHeaders(response)) : Response.success(new JSONObject(), HttpHeaderParser.parseCacheHeaders(response));
                    }
                    catch (JSONException ex)
                    {
                        ex.printStackTrace();
                    }
                    catch (UnsupportedEncodingException e)
                    {
                        e.printStackTrace();
                    }
                    return null;
                }
            };
            jsonObjReq.setShouldCache(true);
            VolleySingleton.getInstance().addToRequestQueue(jsonObjReq, tag);
}

请帮忙,我想缓存我的屏幕数据。

编辑

缓存数据

 private String getCache(String url)
    {
        String data = "";
        Cache cache = VolleySingleton.getInstance().getRequestQueue().getCache();
        Cache.Entry entry = cache.get(url);
        if (entry != null)
        {
            try
            {
                data = new String(entry.data, "UTF-8");
                // handle data, like converting it to xml, json, bitmap etc.,
            }
            catch (UnsupportedEncodingException e)
            {
                e.printStackTrace();
            }
        }
        /*else
        {
            // Cached response doesn't exists. Make network call here
        }*/
        return data;
    }

【问题讨论】:

  • 你的离线查看代码在哪里?
  • @mmlooloo 我更新了代码

标签: android caching httprequest android-volley


【解决方案1】:

只需在 **BasicNetwork* 类中添加这一行或修改如下

  @Override
  public NetworkResponse performRequest(Request<?> request) throws VolleyError {
    long requestStart = SystemClock.elapsedRealtime();
    while (true) {

        HttpResponse httpResponse = null;
        byte[] responseContents = null;
        Map<String, String> responseHeaders = Collections.emptyMap();
        try {
         if(!ConnectivityUtils.isNetworkEnabled(BBApplication.getContext())) {
                return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED,
                        request.getCacheEntry().data, responseHeaders, true);
            }

            // Gather headers.
            Map<String, String> headers = new HashMap<String, String>();
            addCacheHeaders(headers, request.getCacheEntry());
            httpResponse = mHttpStack.performRequest(request, headers);
            StatusLine statusLine = httpResponse.getStatusLine();
            int statusCode = statusLine.getStatusCode();
            responseHeaders = convertHeaders(httpResponse.getAllHeaders());
            // Handle cache validation.


            if (statusCode == HttpStatus.SC_NOT_MODIFIED) {
                Cache.Entry entry = request.getCacheEntry();

                if (entry == null) {
                    return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, null, responseHeaders, true, SystemClock.elapsedRealtime() - requestStart);
                }

                // A HTTP 304 response does not have all header fields. We
                // have to use the header fields from the cache entry plus
                // the new ones from the response.
                // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5
                entry.responseHeaders.putAll(responseHeaders);
                return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, entry.data, entry.responseHeaders, true, SystemClock.elapsedRealtime() - requestStart);
            }
            // Some responses such as 204s do not have content.  We must check.
            if (httpResponse.getEntity() != null) {
                responseContents = entityToBytes(httpResponse.getEntity());
            } else {
                // Add 0 byte response as a way of honestly representing a
                // no-content request.
                responseContents = new byte[0];
            }

            // if the request is slow, log it.
            long requestLifetime = SystemClock.elapsedRealtime() - requestStart;
            logSlowRequests(requestLifetime, request, responseContents, statusLine);

            if (statusCode < 200 || statusCode > 299) {
                throw new IOException();
            }
            return new NetworkResponse(statusCode, responseContents, responseHeaders, false, SystemClock.elapsedRealtime() - requestStart);
        } catch (SocketTimeoutException e) {
            attemptRetryOnException("socket", request, new TimeoutError());
        } catch (ConnectTimeoutException e) {
            attemptRetryOnException("connection", request, new TimeoutError());
        } catch (NoHttpResponseException e) {
            attemptRetryOnException("socket", request, new TimeoutError());
        } catch (UnknownHostException e) {
            attemptRetryOnException("socket", request, new TimeoutError());
        } catch (MalformedURLException e) {
            throw new RuntimeException("Bad URL " + request.getUrl(), e);
        } catch (IOException e) {
            int statusCode = 0;
            NetworkResponse networkResponse = null;
            if (httpResponse != null) {
                statusCode = httpResponse.getStatusLine().getStatusCode();
            } else {
                throw new NoConnectionError(e);
            }
            VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl());
            if (responseContents != null) {
                networkResponse = new NetworkResponse(statusCode, responseContents, responseHeaders, false, SystemClock.elapsedRealtime() - requestStart);
                if (statusCode == HttpStatus.SC_UNAUTHORIZED || statusCode == HttpStatus.SC_FORBIDDEN) {
                    attemptRetryOnException("auth", request, new AuthFailureError(networkResponse));
                } else {
                    // TODO: Only throw ServerError for 5xx status codes.
                    throw new ServerError(networkResponse);
                }
            } else {
                throw new NetworkError(networkResponse);
            }
        }
    }
}

对于数据请求到期,您可以使用自己的 HttpHeaderParser

更改 Cached.Entry

点击BasicNetwork

这段代码会做什么,它将检查互联网连接和网络调用,如果它有缓存副本,则恢复。

注意 API 响应应该是可缓存的,因为 Volley 仅在 Response Header 允许的情况下缓存数据。 See here for Cached Control Header

【讨论】:

  • @RishabhSrivastava 您必须拥有 volley 代码作为模块,或者扩展 BasicNetwork 类并覆盖上述代码。
【解决方案2】:

要使用Volley 缓存任何内容,您需要具备两件事:

1) 服务器允许你缓存它。它通常出现在cache control tag 中的HTTP header 中。

2) 你保存它,或者在这种情况下你告诉Volly 保存。

所以我认为您的问题排在第一位。这意味着服务器不允许您缓存这些文件,为了确认我的回答,您可以执行以下操作之一:

  1. mozilla 下载此插件(RESTClient)并发送您的请求并检查头文件以进行缓存控制。如果服务器不允许您缓存,您将看到类似下图的内容,notice cache control tag

  1. headerValue = headers.get("Cache-Control");HttpHeaderParse 类中设置断点,看看Volley 想要解析cache control tag 时发生了什么。

【讨论】:

  • 我检查了标题,响应中的 Cache-Control 是 no-chache。那就是说我不能缓存?
  • 是的,这意味着 Volley 不缓存它,您可以更改源代码,也可以自己手动缓存,然后将其插入到 onResponsecallbacke 中的 Volley 缓存中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多