我正在使用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);
}
作为参考,请检查Android Volley + JSONObjectRequest Caching