Reputation: 5990
I have added volley for request to get Json object, If wifi is turned on then it takes data but does not get in case of offline mode even cache is enabled for the request.
I do the following code
public class VolleySingleton extends Application
{
public static final String TAG = VolleySingleton.class.getSimpleName();
private RequestQueue mRequestQueue;
private static VolleySingleton mInstance;
private ImageLoader mImageLoader;
private final String DEFAULT_CACHE_DIR = "sl_cache";
@Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
}
@Override
public void onCreate()
{
super.onCreate();
mInstance = this;
}
public static synchronized VolleySingleton getInstance()
{
return mInstance;
}
public ImageLoader getImageLoader()
{
getRequestQueue();
if (mImageLoader == null)
{
mImageLoader = new ImageLoader(this.mRequestQueue, new LruBitmapCache());
}
return this.mImageLoader;
}
public <T> void addToRequestQueue(Request<T> req, String tag)
{
// set the default tag if tag is empty
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req)
{
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag)
{
if (mRequestQueue != null)
{
mRequestQueue.cancelAll(tag);
}
}
public RequestQueue getRequestQueue()
{
if (mRequestQueue == null)
{
Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024 * 10); // 10MB cap
Network network = new BasicNetwork(new HurlStack());
mRequestQueue = new RequestQueue(cache, network);
mRequestQueue.start();
}
return mRequestQueue;
}
}
private void getData(String url, String tag)
{
final JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>()
{
@Override
public void onResponse(JSONObject response)
{
Log.wtf("HOME", response.toString());
String result = parseData(response.toString());
postProcessing(result);
//SocialLadder.getInstance().getRequestQueue().getCache().invalidate(url, true);
}
}, new Response.ErrorListener()
{
@Override
public void onErrorResponse(VolleyError error)
{
VolleyLog.wtf("HOME", "Error: " + error.getMessage());
stopRefresher();
}
})
{
@Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response)
{
try
{
String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
return !jsonString.isEmpty() ? Response.success(new JSONObject(jsonString), HttpHeaderParser.parseCacheHeaders(response)) : Response.success(new JSONObject(), HttpHeaderParser.parseCacheHeaders(response));
}
catch (JSONException ex)
{
ex.printStackTrace();
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
return null;
}
};
jsonObjReq.setShouldCache(true);
VolleySingleton.getInstance().addToRequestQueue(jsonObjReq, tag);
}
Please help, I want to cache my screen data.
Edit
Cache Data
private String getCache(String url)
{
String data = "";
Cache cache = VolleySingleton.getInstance().getRequestQueue().getCache();
Cache.Entry entry = cache.get(url);
if (entry != null)
{
try
{
data = new String(entry.data, "UTF-8");
// handle data, like converting it to xml, json, bitmap etc.,
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
}
/*else
{
// Cached response doesn't exists. Make network call here
}*/
return data;
}
Upvotes: 2
Views: 8181
Reputation: 1451
Just add this line in **BasicNetwork* class or modify it as follow
@Override
public NetworkResponse performRequest(Request<?> request) throws VolleyError {
long requestStart = SystemClock.elapsedRealtime();
while (true) {
HttpResponse httpResponse = null;
byte[] responseContents = null;
Map<String, String> responseHeaders = Collections.emptyMap();
try {
if(!ConnectivityUtils.isNetworkEnabled(BBApplication.getContext())) {
return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED,
request.getCacheEntry().data, responseHeaders, true);
}
// Gather headers.
Map<String, String> headers = new HashMap<String, String>();
addCacheHeaders(headers, request.getCacheEntry());
httpResponse = mHttpStack.performRequest(request, headers);
StatusLine statusLine = httpResponse.getStatusLine();
int statusCode = statusLine.getStatusCode();
responseHeaders = convertHeaders(httpResponse.getAllHeaders());
// Handle cache validation.
if (statusCode == HttpStatus.SC_NOT_MODIFIED) {
Cache.Entry entry = request.getCacheEntry();
if (entry == null) {
return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, null, responseHeaders, true, SystemClock.elapsedRealtime() - requestStart);
}
// A HTTP 304 response does not have all header fields. We
// have to use the header fields from the cache entry plus
// the new ones from the response.
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5
entry.responseHeaders.putAll(responseHeaders);
return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, entry.data, entry.responseHeaders, true, SystemClock.elapsedRealtime() - requestStart);
}
// Some responses such as 204s do not have content. We must check.
if (httpResponse.getEntity() != null) {
responseContents = entityToBytes(httpResponse.getEntity());
} else {
// Add 0 byte response as a way of honestly representing a
// no-content request.
responseContents = new byte[0];
}
// if the request is slow, log it.
long requestLifetime = SystemClock.elapsedRealtime() - requestStart;
logSlowRequests(requestLifetime, request, responseContents, statusLine);
if (statusCode < 200 || statusCode > 299) {
throw new IOException();
}
return new NetworkResponse(statusCode, responseContents, responseHeaders, false, SystemClock.elapsedRealtime() - requestStart);
} catch (SocketTimeoutException e) {
attemptRetryOnException("socket", request, new TimeoutError());
} catch (ConnectTimeoutException e) {
attemptRetryOnException("connection", request, new TimeoutError());
} catch (NoHttpResponseException e) {
attemptRetryOnException("socket", request, new TimeoutError());
} catch (UnknownHostException e) {
attemptRetryOnException("socket", request, new TimeoutError());
} catch (MalformedURLException e) {
throw new RuntimeException("Bad URL " + request.getUrl(), e);
} catch (IOException e) {
int statusCode = 0;
NetworkResponse networkResponse = null;
if (httpResponse != null) {
statusCode = httpResponse.getStatusLine().getStatusCode();
} else {
throw new NoConnectionError(e);
}
VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl());
if (responseContents != null) {
networkResponse = new NetworkResponse(statusCode, responseContents, responseHeaders, false, SystemClock.elapsedRealtime() - requestStart);
if (statusCode == HttpStatus.SC_UNAUTHORIZED || statusCode == HttpStatus.SC_FORBIDDEN) {
attemptRetryOnException("auth", request, new AuthFailureError(networkResponse));
} else {
// TODO: Only throw ServerError for 5xx status codes.
throw new ServerError(networkResponse);
}
} else {
throw new NetworkError(networkResponse);
}
}
}
}
and for data request expiry you can change the Cached.Entry using using own HttpHeaderParser
Click for BasicNetwork
What is this code will do it will check for internet connection and Network call and revert if it has cached copy .
Note The API response should be cache-able because Volley only cache data if Response Header permits . See here for Cached Control Header
Upvotes: 6
Reputation: 18977
In order to cache anything with Volley
you need to have two things:
1) server allows you to cache it. it usually appears in a cache control tag
in the HTTP header
.
2) you save it or in this scenario you tell the Volly
to save.
so i think your problem is in number one. that means the server dose not allow you to cache those files, in order to confirm my answer you can do one of these things:
mozilla
and send your request and check the header file for cache control. if the server dose not allow you to cache you will see something like below image, notice cache control tag
headerValue = headers.get("Cache-Control");
at HttpHeaderParse
class and see whats going on when Volley
wants to parse the cache control tag
.Upvotes: 5