Cache.Entry not getting json data

I use volly to get the data and it works fine, except that my json array is not stored in the cache.

Here is my code:

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); } 

I already declared the Appcontroller in the manifest, but I do not know why caching does not work.

Here is my json_data

fetchImage() works because there is data in recyclerview . However, when I try to recover data offline, it shows nothing, because my cache cannot store any data.

+7
android nullpointerexception android-volley
source share
1 answer

By default, Volley only caches data if it allows a response header. Volley caches the response based on the following response headers:
1. Cache-Control
2. Expires
3.maxAge

See below for more details.

 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; } 

You can change the default cache policy by overriding the Request object. You can override JsonObjectRequest, for example:

 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, JSONObject jsonRequest, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) { super(url, jsonRequest, listener, 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; } } 

Update the fetchImage function as follows:

 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(), "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); } 

For reference: Android caching Volley + JSONObjectRequest

+2
source share

All Articles