2016-08-19 56 views
7

我使用volly來完美地檢索數據及其工作,除了我的json數組沒有存儲在緩存中。Cache.Entry沒有獲取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數據。但是,當我嘗試脫機檢索數據時,它顯示任何內容,因爲我的緩存無法存儲任何數據。

+0

你在哪裏,即使將數據存儲到緩存?你得到一個條目,然後檢查它是否爲空並使用它,但是該條目如何被存儲? –

+1

你見過這篇文章嗎? http://stackoverflow.com/questions/23883329/are-android-volley-requests-automatically-cached –

+1

是的...我的入口變量是空的..所以只有其他部分打印.. –

回答

2

默認情況下,如果Response Header允許,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, 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; 
    } 
} 

更新您的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(), 
           "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); 
} 

僅供參考,請Android Volley + JSONObjectRequest Caching

+0

嘿..當我停止從RAM應用程序..緩存也清除.. –

+0

你如何停止內存應用程序? – abhishesh

+0

我的意思是清晰的ram進程,當我清除ram進程緩存的時候也清楚, –