我正在使用volly来完美地检索数据及其工作,除了我的json数组没有存储在缓存中.
这是我的代码:
private void getCacheValue() { Cache cache = AppController.getInstance().getRequestQueue().getCache(); Cache.Entry entry = cache.get(Endpoints.product_url); if(entry != null){ Log.w("Logdata:",""+ entry.toString()); try { String data = new String(entry.data,"UTF-8"); JSONArray jsonArray = new JSONArray(data); // handle data,like converting it to xml,json,bitmap etc.,Log.v("Hello",data); listProduct.clear(); for (int i = 0; i < jsonArray.length(); i++) { try { JSONObject object = jsonArray.getJSONObject(i); ItemCategories image = new ItemCategories(); image.setCategoryItem(object.getString(key_title)); image.setUrlThumb(object.getString(key_image)); listProduct.add(image); } catch (JSONException e) { Log.e(TAG,"Json parsing error: " + e.getMessage()); } } adapterProductList.notifyDataSetChanged(); progressBarMain.setVisibility(View.GONE); internetError.setVisibility(View.GONE); recycleProductList.setVisibility(View.VISIBLE); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); Log.v("JSON EXCEPTION","DECLINE"); } } else { if(isNetworkAvailable()) { fetchImages(); } else { progressBarMain.setVisibility(View.GONE); internetError.setVisibility(View.VISIBLE); } } } private void fetchImages() { JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.GET,Endpoints.product_url(String) null,new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { listProduct.clear(); try { JSONArray routes = response.getJSONArray(key_product); for (int i = 0; i < routes.length(); i++) { JSONObject object = routes.getJSONObject(i); ItemCategories categories = new ItemCategories(); categories.setCategoryItem(object.getString(key_title)); categories.setUrlThumb(object.getString(key_image)); listProduct.add(categories); } adapterProductList.notifyDataSetChanged(); progressBarMain.setVisibility(View.GONE); internetError.setVisibility(View.GONE); recycleProductList.setVisibility(View.VISIBLE); } catch (JSONException e) { e.printStackTrace(); Toast.makeText(getApplicationContext(),"Error: " + e.getMessage(),Toast.LENGTH_LONG).show(); } } },new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { VolleyLog.d(TAG,"Error: " + error.getMessage()); } }); // Adding request to request queue AppController.getInstance().addToRequestQueue(jsObjRequest); }
我已经在清单中声明了Appcontroller,但我不知道为什么缓存不起作用.
这是我的json_data
fetchImage()正在运行,因为recyclerview中有数据.但是,当我尝试脱机检索数据时,它会显示任何数据,因为我的缓存无法存储任何数据.
解决方法
默认情况下,如果响应标头允许,Volley仅缓存数据.
Volley根据以下响应标头缓存响应:
1.缓存控制
2.到期
3. maxAge
Volley根据以下响应标头缓存响应:
1.缓存控制
2.到期
3. maxAge
请参阅以下功能了解详情:
public static Cache.Entry parseCacheHeaders(NetworkResponse response) { long now = System.currentTimeMillis(); Map<String,String> headers = response.headers; long serverDate = 0; long lastModified = 0; long serverExpires = 0; long softExpire = 0; long finalExpire = 0; long maxAge = 0; long staleWhileRevalidate = 0; boolean hasCacheControl = false; boolean mustRevalidate = false; String serverEtag = null; String headerValue; headerValue = headers.get("Date"); if (headerValue != null) { serverDate = parseDateAsEpoch(headerValue); } headerValue = headers.get("Cache-Control"); if (headerValue != null) { hasCacheControl = true; String[] tokens = headerValue.split(","); for (int i = 0; i < tokens.length; i++) { String token = tokens[i].trim(); if (token.equals("no-cache") || token.equals("no-store")) { return null; } else if (token.startsWith("max-age=")) { try { maxAge = Long.parseLong(token.substring(8)); } catch (Exception e) { } } else if (token.startsWith("stale-while-revalidate=")) { try { staleWhileRevalidate = Long.parseLong(token.substring(23)); } catch (Exception e) { } } else if (token.equals("must-revalidate") || token.equals("proxy-revalidate")) { mustRevalidate = true; } } } headerValue = headers.get("Expires"); if (headerValue != null) { serverExpires = parseDateAsEpoch(headerValue); } headerValue = headers.get("Last-Modified"); if (headerValue != null) { lastModified = parseDateAsEpoch(headerValue); } serverEtag = headers.get("ETag"); // Cache-Control takes precedence over an Expires header,even if both exist and Expires // is more restrictive. if (hasCacheControl) { softExpire = now + maxAge * 1000; finalExpire = mustRevalidate ? softExpire : softExpire + staleWhileRevalidate * 1000; } else if (serverDate > 0 && serverExpires >= serverDate) { // Default semantic for Expire header in HTTP specification is softExpire. softExpire = now + (serverExpires - serverDate); finalExpire = softExpire; } Cache.Entry entry = new Cache.Entry(); entry.data = response.data; entry.etag = serverEtag; entry.softTtl = softExpire; entry.ttl = finalExpire; entry.serverDate = serverDate; entry.lastModified = lastModified; entry.responseHeaders = headers; return entry; }
您可以通过覆盖Request对象来更改默认缓存策略.
您可以覆盖JsonObjectRequest,如:
public class CustomJsonObjectRequest extends JsonObjectRequest { public CustomJsonObjectRequest(int method,String url,JSONObject jsonRequest,Response.Listener<JSONObject> listener,Response.ErrorListener errorListener) { super(method,url,jsonRequest,listener,errorListener); } public CustomJsonObjectRequest(String url,Response.ErrorListener errorListener) { super(url,errorListener); } @Override protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) { try { String jsonString = new String(response.data,HttpHeaderParser.parseCharset(response.headers,PROTOCOL_CHARSET)); return Response.success(new JSONObject(jsonString),parseIgnoreCacheHeaders(response)); } catch (UnsupportedEncodingException e) { return Response.error(new ParseError(e)); } catch (JSONException je) { return Response.error(new ParseError(je)); } } 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; } }
将fetchImage函数更新为:
private void fetchImages() { CustomJsonObjectRequest jsObjRequest = new CustomJsonObjectRequest() (Request.Method.GET,Endpoints.product_url,(String) null,new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { listProduct.clear(); try { JSONArray routes = response.getJSONArray(key_product); for (int i = 0; i < routes.length(); i++) { JSONObject object = routes.getJSONObject(i); ItemCategories categories = new ItemCategories(); categories.setCategoryItem(object.getString(key_title)); categories.setUrlThumb(object.getString(key_image)); listProduct.add(categories); } adapterProductList.notifyDataSetChanged(); progressBarMain.setVisibility(View.GONE); internetError.setVisibility(View.GONE); recycleProductList.setVisibility(View.VISIBLE); } catch (JSONException e) { e.printStackTrace(); Toast.makeText(getApplicationContext(),Toast.LENGTH_LONG).show(); } } },new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { VolleyLog.d(TAG,"Error: " + error.getMessage()); } }); // Adding request to request queue AppController.getInstance().addToRequestQueue(jsObjRequest); }