Android:Volley无法使用缓存离线工作

NAS*_*SER 2 android caching httprequest android-volley

我已经添加了volley来获取Json对象的请求,如果打开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);
}
Run Code Online (Sandbox Code Playgroud)

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

编辑

缓存数据

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

mml*_*loo 5

为了缓存任何东西Volley你需要有两件事:

1)服务器允许您缓存它.它通常出现在cache control tagHTTP header.

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

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

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

在此输入图像描述

  1. headerValue = headers.get("Cache-Control");HttpHeaderParse课堂上设置断点,看看Volley想要解析的时候会发生什么cache control tag.


Vip*_*ahu 5

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

对于数据请求到期,您可以使用自己的HttpHeaderParser更改Cached.Entry

单击" BasicNetwork"

该代码将执行此操作将检查Internet连接和网络调用,如果它已缓存副本,则还原.

注意API响应应该是可缓存的,因为如果响应标头允许,Volley仅缓存数据.请参阅此处了解缓存控制标头