diff --git a/src/com/androidquery/AbstractAQuery.java b/src/com/androidquery/AbstractAQuery.java index bc213bab..022b0e3a 100644 --- a/src/com/androidquery/AbstractAQuery.java +++ b/src/com/androidquery/AbstractAQuery.java @@ -1987,8 +1987,30 @@ public T ajax(String url, Class type, AjaxCallback callback){ */ public T ajax(String url, Class type, long expire, AjaxCallback callback){ + return ajax(url, type, expire, expire, callback); + } + + /** + * Ajax call with various callback data types with file caching. + * + * The expire param is the duration to consider cached data expired (if hit). + * For example, expire = 15 * 60 * 1000 means if the cache data is within 15 minutes old, + * return cached data immediately, otherwise go fetch the source again. + * + * + * @param url url + * @param type data type + * @param expire duration in millseconds, 0 = always use cache + * @param fresh duration in millseconds, 0 = always use cache + * @param callback callback handler + * @return self + * + * + */ + + public T ajax(String url, Class type, long expire, long fresh, AjaxCallback callback){ - callback.type(type).url(url).fileCache(true).expire(expire); + callback.type(type).url(url).fileCache(true).expire(expire, fresh); return ajax(callback); } @@ -2020,7 +2042,6 @@ public T ajax(String url, Class type, Object handler, String callback){ } - /** * Ajax call with various callback data types with file caching. * @@ -2040,9 +2061,33 @@ public T ajax(String url, Class type, Object handler, String callback){ */ public T ajax(String url, Class type, long expire, Object handler, String callback){ + return ajax(url, type, expire, expire, handler, callback); + } + + + /** + * Ajax call with various callback data types with file caching. + * + * The expire param is the duration to consider cache data expired (if hit). + * For example, expire = 15 * 60 * 1000 means if the cache data is within 15 minutes old, + * return cached data immediately, otherwise go fetch the source again. + * + * + * @param url url + * @param type data type + * @param expire duration in millseconds, 0 = always use cache + * @param fresh duration in millseconds, 0 = always use cache + * @param handler the handler object with the callback method to be called + * @param callback callback method name + * @return self + * + * + */ + + public T ajax(String url, Class type, long expire, long fresh, Object handler, String callback){ AjaxCallback cb = new AjaxCallback(); - cb.type(type).weakHandler(handler, callback).fileCache(true).expire(expire); + cb.type(type).weakHandler(handler, callback).fileCache(true).expire(expire, fresh); return ajax(url, type, cb); } @@ -2200,8 +2245,6 @@ public T sync(AjaxCallback callback){ return self(); } - - /** * Cache the url to file cache without any callback. * @@ -2214,7 +2257,23 @@ public T sync(AjaxCallback callback){ * @see testCache */ public T cache(String url, long expire){ - return ajax(url, byte[].class, expire, null, null); + return cache(url, expire, expire); + } + + /** + * Cache the url to file cache without any callback. + * + * + * @param url url to cache + * @param expire duration in millseconds, 0 = never consider cached data as expired + * @param fresh duration in millseconds, 0 = never consider cached data as expired + * + * @return self + * + * @see testCache + */ + public T cache(String url, long expire, long fresh){ + return ajax(url, byte[].class, expire, fresh, null, null); } diff --git a/src/com/androidquery/callback/AbstractAjaxCallback.java b/src/com/androidquery/callback/AbstractAjaxCallback.java index 1b1911c5..6d654097 100644 --- a/src/com/androidquery/callback/AbstractAjaxCallback.java +++ b/src/com/androidquery/callback/AbstractAjaxCallback.java @@ -148,6 +148,7 @@ public abstract class AbstractAjaxCallback implements Runnable{ private boolean redirect = true; private long expire; + private long fresh; private String encoding = "UTF-8"; private WeakReference act; @@ -395,6 +396,22 @@ public K uiCallback(boolean uiCallback){ */ public K expire(long expire){ this.expire = expire; + this.fresh = expire; + return self(); + } + + /** + * The expire and fresh duation for filecache. + * If a cached copy will be served if a cached file exists within current time minus fresh duration. + * But, with network error case and if a cached copy will be served if a cached file exists within current time minus expire duration + * + * @param expire the expire + * @param fresh the fresh + * @return self + */ + public K expire(long expire, long fresh){ + this.expire = expire; + this.fresh = fresh; return self(); } @@ -911,15 +928,17 @@ protected void filePut(String url, T object, File file, byte[] data){ } - protected File accessFile(File cacheDir, String url){ + protected File accessFile(File cacheDir, String url, boolean onlyFresh){ if(expire < 0) return null; + long limit = onlyFresh ? fresh : expire; + File file = AQUtility.getExistedCacheByUrl(cacheDir, url); if(file != null && expire != 0){ long diff = System.currentTimeMillis() - file.lastModified(); - if(diff > expire){ + if(diff > limit){ return null; } } @@ -1072,11 +1091,9 @@ public void run() { } private void backgroundWork(){ - if(!refresh){ - if(fileCache){ - fileWork(); + fileWork(true); } } @@ -1088,7 +1105,16 @@ private void backgroundWork(){ networkWork(); } - + if(result == null && !refresh && fileCache){ + AjaxStatus prevStatus = status; + status = new AjaxStatus(); + + fileWork(false); + + if (result == null){ + status = prevStatus; + } + } } private String getCacheUrl(){ @@ -1113,9 +1139,9 @@ private String getNetworkUrl(String url){ return result; } - private void fileWork(){ + private void fileWork(boolean freshOnly){ - File file = accessFile(cacheDir, getCacheUrl()); + File file = accessFile(cacheDir, getCacheUrl(), freshOnly); //if file exist if(file != null){ diff --git a/src/com/androidquery/callback/BitmapAjaxCallback.java b/src/com/androidquery/callback/BitmapAjaxCallback.java index 3150d70d..4d3598ae 100644 --- a/src/com/androidquery/callback/BitmapAjaxCallback.java +++ b/src/com/androidquery/callback/BitmapAjaxCallback.java @@ -450,13 +450,13 @@ private Bitmap bmGet(String path, byte[] data){ } @Override - protected File accessFile(File cacheDir, String url){ + protected File accessFile(File cacheDir, String url, boolean onlyFresh){ if(imageFile != null && imageFile.exists()){ return imageFile; } - return super.accessFile(cacheDir, url); + return super.accessFile(cacheDir, url, onlyFresh); }