我正在使用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);
- }