1

my below sample code work fine without any some problem, this sample code can cache received data from url and using that when device doesnt have any internet connection.

but this code have a big deficiency, it is when device have internet connection i cant recache and get newest data from internet and recache again until device doesnt have connection, some data can be image or json array or json object

public class MainActivity extends AppCompatActivity {

    private final Context mContext = this;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final TextView textView = (TextView) findViewById(R.id.textView);

        RequestQueue queue = Volley.newRequestQueue(this);
        String url = "http://192.168.1.2/test";

        CacheRequest cacheRequest = 
           new CacheRequest(0, url, new Response.Listener<NetworkResponse>() {
            @Override
            public void onResponse(NetworkResponse response) {
                try {
                    final String jsonString = new String(response.data,
                            HttpHeaderParser.parseCharset(response.headers));
                    JSONObject jsonObject = new JSONObject(jsonString);
                    textView.setText(jsonObject.toString(5));
                    Log.e('OutPut',jsonObject.toString());
                } catch (UnsupportedEncodingException | JSONException e) {
                    e.printStackTrace();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Toast.makeText(mContext, "onErrorResponse:\n\n" + error.toString(), Toast.LENGTH_SHORT).show();
            }
        });
        queue.add(cacheRequest);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        int id = item.getItemId();

        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private class CacheRequest extends Request<NetworkResponse> {
        private final Response.Listener<NetworkResponse> mListener;
        private final Response.ErrorListener mErrorListener;

        public CacheRequest(int method, String url, Response.Listener<NetworkResponse> listener, Response.ErrorListener errorListener) {
            super(method, url, errorListener);
            this.mListener = listener;
            this.mErrorListener = errorListener;
        }


        @Override
        protected Response<NetworkResponse> parseNetworkResponse(NetworkResponse response) {
            Cache.Entry cacheEntry = HttpHeaderParser.parseCacheHeaders(response);
            if (cacheEntry == null) {
                cacheEntry = new Cache.Entry();
            }
            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
            long now = System.currentTimeMillis();
            final long softExpire = now + cacheHitButRefreshed;
            final long ttl = now + cacheExpired;
            cacheEntry.data = response.data;
            cacheEntry.softTtl = softExpire;
            cacheEntry.ttl = ttl;
            String headerValue;
            headerValue = response.headers.get("Date");
            if (headerValue != null) {
                cacheEntry.serverDate = HttpHeaderParser.parseDateAsEpoch(headerValue);
            }
            headerValue = response.headers.get("Last-Modified");
            if (headerValue != null) {
                cacheEntry.lastModified = HttpHeaderParser.parseDateAsEpoch(headerValue);
            }
            cacheEntry.responseHeaders = response.headers;
            return Response.success(response, cacheEntry);
        }

        @Override
        protected void deliverResponse(NetworkResponse response) {
            mListener.onResponse(response);
        }

        @Override
        protected VolleyError parseNetworkError(VolleyError volleyError) {
            return super.parseNetworkError(volleyError);
        }

        @Override
        public void deliverError(VolleyError error) {
            mErrorListener.onErrorResponse(error);
        }
    }
}
  • maybe you need to clean cache first then recache, volley has a default 5mb cache size, so that might get full and prevent any future caching –  Feb 14 '16 at 06:41
  • @OnurTaş merhaba Onur, i said into topic: `recache and get newest data from internet and recache again until device doesnt have connection` –  Feb 14 '16 at 06:43
  • @OnurTaş yes, how to clear cache and prepair volley to get newest data? –  Feb 14 '16 at 06:51

2 Answers2

1

It will cache only once because onCreate method is called once the app created..

most suitable solution would be this:

You need to have a Service which uses AlarmManager for, say, every 5 minutes to trigger itself. And in this service you can cache the newest data in the background, of course for smaller time unit, more battery will be consumed.

update for cache resizing

RequestQueue volleyQueue = Volley.newRequestQueue(this);
DiskBasedCache cache = new DiskBasedCache(getCacheDir(), 16 * 1024 * 1024);
volleyQueue = new RequestQueue(cache, new BasicNetwork(new HurlStack()));
volleyQueue.start();

according to that discussion volley's cache can be manipulated, but when it gets full, automatically replaces new data with the old one so, cache size is not the focus right now.

update for cache cleaning

mahdi, according to official link of google volley's Cache class, there is a method called invalidate(), which invalidates the cached data, and next time volley checks if data was valid and update it.

you can appereantly delete cache for every 30 minutes according to this discussion:

serverDate: AppController.getInstance().getRequestQueue().getCache().get(url).serverDate

getMinutesDifference is method calculates time passed, can be found on reference link.

Calendar calendar = Calendar.getInstance();
long serverDate = AppController.getInstance().getRequestQueue().getCache().get(url).serverDate;
if(getMinutesDifference(serverDate, calendar.getTimeInMillis()) >=30)
{
   AppController.getInstance().getRequestQueue().getCache().invalidate(url, true);
}
Community
  • 1
  • 1
  • you said `of course for smaller time unit, more battery will be consumed.` then whats best solution to resolve this problem? problem means recache volley cashe-data when device connected to internet, many application use this library, how to resolved by them? –  Feb 14 '16 at 06:56
  • mahdi, 30 minutes would be ideal I guess, if the data consist of mostly images, then maybe 40 minutes. But you definitely need a service if you want to automate the recaching process –  Feb 14 '16 at 06:59
  • `update for cache cleaning` not good for use offline data on device, because every moment data on server can be update and if user dont have connection, this method clear cache and user must be connected to get data or data was cached,then user maybe dont have cache data on long time, because cache is cleard every 30 minute,ok? –  Feb 15 '16 at 09:12
  • you wont clean if you dont have connection. you can clean it when you fill it with latest data, meaning, it happens when you have connection... –  Feb 15 '16 at 11:53
0

You can first check your Internet connection, if you have connection you can clear the cache and reload

ConnectivityManager connMgr = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = connMgr.getActiveNetworkInfo(); if (networkInfo != null && networkInfo.isConnected()) { MySocialMediaSingleton.getInstance(getContext()).getRequestQueue().getCache().invalidate("http://server/json.php?page=1", true); } //Calling again method to get data to fetch data getData();

Vladimir Salguero
  • 5,609
  • 3
  • 42
  • 47