2016-08-19 49 views
7

Używam volly do pobierania danych i ich pracy doskonale, z tym że moja tablica json nie zapisuje w pamięci podręcznej.Pamięć podręczna.Nie otrzymuję danych json

Oto mój kod:

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

już zadeklarował Appcontroller w manifeście, ale nie wiem dlaczego buforowanie nie działa.

Oto mój json_data

fetchImage() pracuje, ponieważ nie ma danych w recyclerview. Jednak gdy próbuję odzyskać dane w trybie offline, pokazuje się, ponieważ moja pamięć podręczna nie może przechowywać żadnych danych.

+0

skąd nawet przechowują dane do pamięci podręcznej? Otrzymasz wpis, a następnie sprawdzisz, czy jest on pusty i używa go, ale w jaki sposób zapisuje się ten wpis? –

+1

Czy widziałeś ten post? http://stackoverflow.com/questions/23883329/are-android-volley-requests-automatically-cached –

+1

tak ... moja zmienna wejściowa jest pusta .. więc tylko część inna jest drukowana .. –

Odpowiedz

2

Domyślnie Volley zapisuje dane tylko w pamięci podręcznej, jeśli pozwala na to nagłówek odpowiedzi. Volley buforuje odpowiedź na podstawie następujących nagłówków odpowiedzi:
1. Cache-Control
2. wygasa
3. maxAge

patrz poniżej funkcji szczegółowe informacje:

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

można zmienić domyślna polityka pamięci podręcznej poprzez przesłanianie obiektu żądania. Można zastąpić JsonObjectRequest jak:

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

zaktualizować swój fetchImage funkcję jak:

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

odsyłającym sprawdzić Android Volley + JSONObjectRequest Caching

+0

hej .. kiedy zatrzymam aplikację z pamięci RAM .. cache również wyczyszczone .. –

+0

jak zatrzymałeś aplikację z pamięci RAM? – abhishesh

+0

Mam na myśli jasne proces RAM, kiedy wyczyść pamięć podręczną proces RAM również jasne, –