diff options
Diffstat (limited to 'main/src/cgeo')
-rw-r--r-- | main/src/cgeo/geocaching/activity/Progress.java | 8 | ||||
-rw-r--r-- | main/src/cgeo/geocaching/cgBase.java | 53 | ||||
-rw-r--r-- | main/src/cgeo/geocaching/cgeodetail.java | 51 | ||||
-rw-r--r-- | main/src/cgeo/geocaching/cgeopopup.java | 11 | ||||
-rw-r--r-- | main/src/cgeo/geocaching/connector/AbstractConnector.java | 5 | ||||
-rw-r--r-- | main/src/cgeo/geocaching/connector/GCConnector.java | 4 | ||||
-rw-r--r-- | main/src/cgeo/geocaching/connector/IConnector.java | 5 | ||||
-rw-r--r-- | main/src/cgeo/geocaching/connector/opencaching/ApiOpenCachingConnector.java | 5 | ||||
-rw-r--r-- | main/src/cgeo/geocaching/maps/CGeoMap.java | 42 | ||||
-rw-r--r-- | main/src/cgeo/geocaching/utils/CancellableHandler.java | 112 |
10 files changed, 238 insertions, 58 deletions
diff --git a/main/src/cgeo/geocaching/activity/Progress.java b/main/src/cgeo/geocaching/activity/Progress.java index ddb98b2..6edf23e 100644 --- a/main/src/cgeo/geocaching/activity/Progress.java +++ b/main/src/cgeo/geocaching/activity/Progress.java @@ -2,6 +2,7 @@ package cgeo.geocaching.activity; import android.app.ProgressDialog; import android.content.Context; +import android.os.Message; /** * progress dialog wrapper for easier management of resources @@ -17,9 +18,12 @@ public class Progress { dialog = null; } - public synchronized void show(Context context, String title, String message, boolean indeterminate, boolean cancelable) { + public synchronized void show(final Context context, final String title, final String message, final boolean indeterminate, final Message cancelMessage) { if (dialog == null) { - dialog = ProgressDialog.show(context, title, message, indeterminate, cancelable); + dialog = ProgressDialog.show(context, title, message, indeterminate, cancelMessage != null); + if (cancelMessage != null) { + dialog.setCancelMessage(cancelMessage); + } } } diff --git a/main/src/cgeo/geocaching/cgBase.java b/main/src/cgeo/geocaching/cgBase.java index 66a5891..4f2553a 100644 --- a/main/src/cgeo/geocaching/cgBase.java +++ b/main/src/cgeo/geocaching/cgBase.java @@ -12,6 +12,7 @@ import cgeo.geocaching.files.LocParser; import cgeo.geocaching.geopoint.DistanceParser; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.utils.BaseUtils; +import cgeo.geocaching.utils.CancellableHandler; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; @@ -995,19 +996,22 @@ public class cgBase { return caches; } - public static cgCacheWrap parseCache(final String page, final int reason, final Handler handler) { + public static cgCacheWrap parseCache(final String page, final int reason, final CancellableHandler handler) { final cgCacheWrap caches = parseCacheFromText(page, reason, handler); - if (!caches.cacheList.isEmpty()) { + if (caches != null && !caches.cacheList.isEmpty()) { final cgCache cache = caches.cacheList.get(0); getExtraOnlineInfo(cache, page, handler); cache.updated = System.currentTimeMillis(); cache.detailedUpdate = cache.updated; cache.detailed = true; } + if (CancellableHandler.isCancelled(handler)) { + return null; + } return caches; } - static cgCacheWrap parseCacheFromText(final String page, final int reason, final Handler handler) { + static cgCacheWrap parseCacheFromText(final String page, final int reason, final CancellableHandler handler) { sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_details); if (StringUtils.isBlank(page)) { @@ -1203,6 +1207,9 @@ public class cgBase { try { final String spoilers = BaseUtils.getMatch(page, GCConstants.PATTERN_SPOILERS, false, null); if (null != spoilers) { + if (CancellableHandler.isCancelled(handler)) { + return null; + } sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_spoilers); final Matcher matcherSpoilersInside = GCConstants.PATTERN_SPOILERSINSIDE.matcher(spoilers); @@ -1294,6 +1301,9 @@ public class cgBase { wpBegin = page.indexOf("<table class=\"Table\" id=\"ctl00_ContentBody_Waypoints\">"); if (wpBegin != -1) { // parse waypoints + if (CancellableHandler.isCancelled(handler)) { + return null; + } sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_waypoints); final Pattern patternWpType = Pattern.compile("\\/wpttypes\\/sm\\/(.+)\\.jpg", Pattern.CASE_INSENSITIVE); @@ -1422,15 +1432,24 @@ public class cgBase { return caches; } - private static void getExtraOnlineInfo(final cgCache cache, final String page, final Handler handler) { + private static void getExtraOnlineInfo(final cgCache cache, final String page, final CancellableHandler handler) { + if (CancellableHandler.isCancelled(handler)) { + return; + } sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_logs); loadLogsFromDetails(page, cache); + if (CancellableHandler.isCancelled(handler)) { + return; + } sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_elevation); if (cache.coords != null) { cache.elevation = getElevation(cache.coords); } + if (CancellableHandler.isCancelled(handler)) { + return; + } sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_gcvote); final cgRating rating = GCVote.getRating(cache.guid, cache.geocode); if (rating != null) { @@ -2065,7 +2084,7 @@ public class cgBase { return search; } - public cgSearch searchByGeocode(final String geocode, final String guid, final int reason, final boolean forceReload, final Handler handler) { + public cgSearch searchByGeocode(final String geocode, final String guid, final int reason, final boolean forceReload, final CancellableHandler handler) { final cgSearch search = new cgSearch(); if (StringUtils.isBlank(geocode) && StringUtils.isBlank(guid)) { @@ -2953,7 +2972,7 @@ public class cgBase { return path.delete(); } - public void storeCache(cgeoapplication app, Activity activity, cgCache cache, String geocode, int listId, Handler handler) { + public void storeCache(cgeoapplication app, Activity activity, cgCache cache, String geocode, int listId, CancellableHandler handler) { try { // get cache details, they may not yet be complete if (cache != null) { @@ -2975,6 +2994,10 @@ public class cgBase { return; } + if (CancellableHandler.isCancelled(handler)) { + return; + } + final cgHtmlImg imgGetter = new cgHtmlImg(activity, cache.geocode, false, listId, true); // store images from description @@ -2982,6 +3005,10 @@ public class cgBase { Html.fromHtml(cache.getDescription(), imgGetter, null); } + if (CancellableHandler.isCancelled(handler)) { + return; + } + // store spoilers if (CollectionUtils.isNotEmpty(cache.spoilers)) { for (cgImage oneSpoiler : cache.spoilers) { @@ -2989,6 +3016,10 @@ public class cgBase { } } + if (CancellableHandler.isCancelled(handler)) { + return; + } + // store images from logs if (Settings.isStoreLogImages() && cache.logs != null) { for (cgLog log : cache.logs) { @@ -3000,9 +3031,17 @@ public class cgBase { } } + if (CancellableHandler.isCancelled(handler)) { + return; + } + // store map previews StaticMapsProvider.downloadMaps(cache, activity); + if (CancellableHandler.isCancelled(handler)) { + return; + } + app.markStored(cache.geocode, listId); app.removeCacheFromCache(cache.geocode); @@ -3010,7 +3049,7 @@ public class cgBase { handler.sendMessage(new Message()); } } catch (Exception e) { - Log.e(Settings.tag, "cgBase.storeCache: " + e.toString()); + Log.e(Settings.tag, "cgBase.storeCache"); } } diff --git a/main/src/cgeo/geocaching/cgeodetail.java b/main/src/cgeo/geocaching/cgeodetail.java index 3ba3537..0be24ef 100644 --- a/main/src/cgeo/geocaching/cgeodetail.java +++ b/main/src/cgeo/geocaching/cgeodetail.java @@ -8,6 +8,7 @@ import cgeo.geocaching.compatibility.Compatibility; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.IConnector; import cgeo.geocaching.enumerations.CacheType; +import cgeo.geocaching.utils.CancellableHandler; import cgeo.geocaching.utils.CryptUtils; import org.apache.commons.collections.CollectionUtils; @@ -120,9 +121,9 @@ public class cgeodetail extends AbstractActivity { private Progress progress = new Progress(); - private Handler storeCacheHandler = new Handler() { + private class StoreCacheHandler extends CancellableHandler { @Override - public void handleMessage(Message msg) { + public void handleRegularMessage(Message msg) { storeThread = null; try { @@ -137,9 +138,9 @@ public class cgeodetail extends AbstractActivity { } }; - private Handler refreshCacheHandler = new Handler() { + private class RefreshCacheHandler extends CancellableHandler { @Override - public void handleMessage(Message msg) { + public void handleRegularMessage(Message msg) { refreshThread = null; try { @@ -169,9 +170,9 @@ public class cgeodetail extends AbstractActivity { } }; - private Handler loadCacheHandler = new Handler() { + private class LoadCacheHandler extends CancellableHandler { @Override - public void handleMessage(Message msg) { + public void handleRegularMessage(final Message msg) { if (cgBase.UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) { updateStatusMsg((String) msg.obj); } else { @@ -398,6 +399,8 @@ public class cgeodetail extends AbstractActivity { app.setAction(geocode); + final LoadCacheHandler loadCacheHandler = new LoadCacheHandler(); + try { String title = res.getString(R.string.cache); if (StringUtils.isNotBlank(name)) { @@ -405,7 +408,7 @@ public class cgeodetail extends AbstractActivity { } else if (StringUtils.isNotBlank(geocode)) { title = geocode.toUpperCase(); } - progress.show(this, title, res.getString(R.string.cache_dialog_loading_details), true, true); + progress.show(this, title, res.getString(R.string.cache_dialog_loading_details), true, loadCacheHandler.cancelMessage()); } catch (Exception e) { // nothing, we lost the window } @@ -1361,9 +1364,9 @@ public class cgeodetail extends AbstractActivity { private class loadCache extends Thread { - private Handler handler = null; + private CancellableHandler handler = null; - public loadCache(Handler handlerIn) { + public loadCache(CancellableHandler handlerIn) { handler = handlerIn; if (geocode == null && guid == null) { @@ -1420,7 +1423,7 @@ public class cgeodetail extends AbstractActivity { } public void loadLongDesc() { - progress.show(this, null, res.getString(R.string.cache_dialog_loading_description), true, true); + progress.show(this, null, res.getString(R.string.cache_dialog_loading_description), true, null); threadLongDesc = new loadLongDesc(loadDescriptionHandler); threadLongDesc.start(); @@ -1718,7 +1721,9 @@ public class cgeodetail extends AbstractActivity { return; } - progress.show(cgeodetail.this, res.getString(R.string.cache_dialog_offline_save_title), res.getString(R.string.cache_dialog_offline_save_message), true, true); + final StoreCacheHandler storeCacheHandler = new StoreCacheHandler(); + + progress.show(cgeodetail.this, res.getString(R.string.cache_dialog_offline_save_title), res.getString(R.string.cache_dialog_offline_save_message), true, storeCacheHandler.cancelMessage()); if (storeThread != null) { storeThread.interrupt(); @@ -1736,7 +1741,9 @@ public class cgeodetail extends AbstractActivity { return; } - progress.show(cgeodetail.this, res.getString(R.string.cache_dialog_refresh_title), res.getString(R.string.cache_dialog_refresh_message), true, true); + final RefreshCacheHandler refreshCacheHandler = new RefreshCacheHandler(); + + progress.show(cgeodetail.this, res.getString(R.string.cache_dialog_refresh_title), res.getString(R.string.cache_dialog_refresh_message), true, refreshCacheHandler.cancelMessage()); if (refreshThread != null) { refreshThread.interrupt(); @@ -1748,30 +1755,30 @@ public class cgeodetail extends AbstractActivity { } private class storeCacheThread extends Thread { - private Handler handler = null; + final private CancellableHandler handler; - public storeCacheThread(Handler handlerIn) { - handler = handlerIn; + public storeCacheThread(final CancellableHandler handler) { + this.handler = handler; } @Override public void run() { - int reason = (cache.reason > 1) ? cache.reason : 1; + int reason = cache.reason > 1 ? cache.reason : 1; base.storeCache(app, cgeodetail.this, cache, null, reason, handler); } } private class refreshCacheThread extends Thread { - private Handler handler = null; + final private CancellableHandler handler; - public refreshCacheThread(Handler handlerIn) { - handler = handlerIn; + public refreshCacheThread(final CancellableHandler handler) { + this.handler = handler; } @Override public void run() { app.removeCacheFromCache(geocode); - search = base.searchByGeocode(cache.geocode, null, 0, true, null); + search = base.searchByGeocode(cache.geocode, null, 0, true, handler); handler.sendEmptyMessage(0); } @@ -1784,7 +1791,7 @@ public class cgeodetail extends AbstractActivity { return; } - progress.show(cgeodetail.this, res.getString(R.string.cache_dialog_offline_drop_title), res.getString(R.string.cache_dialog_offline_drop_message), true, false); + progress.show(cgeodetail.this, res.getString(R.string.cache_dialog_offline_drop_title), res.getString(R.string.cache_dialog_offline_drop_message), true, null); Thread thread = new dropCacheThread(dropCacheHandler); thread.start(); } @@ -1813,7 +1820,7 @@ public class cgeodetail extends AbstractActivity { showToast(res.getString(R.string.err_watchlist_still_managing)); return; } - progress.show(cgeodetail.this, res.getString(titleId), res.getString(messageId), true, true); + progress.show(cgeodetail.this, res.getString(titleId), res.getString(messageId), true, null); if (watchlistThread != null) { watchlistThread.interrupt(); diff --git a/main/src/cgeo/geocaching/cgeopopup.java b/main/src/cgeo/geocaching/cgeopopup.java index 9f22164..ec9d9f7 100644 --- a/main/src/cgeo/geocaching/cgeopopup.java +++ b/main/src/cgeo/geocaching/cgeopopup.java @@ -3,6 +3,7 @@ package cgeo.geocaching; import cgeo.geocaching.activity.AbstractActivity; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; import cgeo.geocaching.enumerations.CacheType; +import cgeo.geocaching.utils.CancellableHandler; import org.apache.commons.lang3.StringUtils; @@ -53,10 +54,10 @@ public class cgeopopup extends AbstractActivity { } } }; - private Handler storeCacheHandler = new Handler() { + private CancellableHandler storeCacheHandler = new CancellableHandler() { @Override - public void handleMessage(Message msg) { + public void handleRegularMessage(Message msg) { try { if (storeDialog != null) { storeDialog.dismiss(); @@ -566,10 +567,10 @@ public class cgeopopup extends AbstractActivity { private class storeCacheThread extends Thread { - private Handler handler = null; + final private CancellableHandler handler; - public storeCacheThread(Handler handlerIn) { - handler = handlerIn; + public storeCacheThread(final CancellableHandler handler) { + this.handler = handler; } @Override diff --git a/main/src/cgeo/geocaching/connector/AbstractConnector.java b/main/src/cgeo/geocaching/connector/AbstractConnector.java index 4153c76..a0ed628 100644 --- a/main/src/cgeo/geocaching/connector/AbstractConnector.java +++ b/main/src/cgeo/geocaching/connector/AbstractConnector.java @@ -4,8 +4,7 @@ import cgeo.geocaching.cgBase; import cgeo.geocaching.cgCache; import cgeo.geocaching.cgSearch; import cgeo.geocaching.cgeoapplication; - -import android.os.Handler; +import cgeo.geocaching.utils.CancellableHandler; public abstract class AbstractConnector implements IConnector { @@ -45,7 +44,7 @@ public abstract class AbstractConnector implements IConnector { } @Override - public cgSearch searchByGeocode(cgBase base, String geocode, String guid, cgeoapplication app, cgSearch search, int reason, Handler handler) { + public cgSearch searchByGeocode(cgBase base, String geocode, String guid, cgeoapplication app, cgSearch search, int reason, CancellableHandler handler) { return null; } diff --git a/main/src/cgeo/geocaching/connector/GCConnector.java b/main/src/cgeo/geocaching/connector/GCConnector.java index 51dca6d..3c2709f 100644 --- a/main/src/cgeo/geocaching/connector/GCConnector.java +++ b/main/src/cgeo/geocaching/connector/GCConnector.java @@ -8,11 +8,11 @@ import cgeo.geocaching.cgCache; import cgeo.geocaching.cgCacheWrap; import cgeo.geocaching.cgSearch; import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.utils.CancellableHandler; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import android.os.Handler; import android.util.Log; import java.util.ArrayList; @@ -67,7 +67,7 @@ public class GCConnector extends AbstractConnector implements IConnector { } @Override - public cgSearch searchByGeocode(final cgBase base, String geocode, final String guid, final cgeoapplication app, final cgSearch search, final int reason, final Handler handler) { + public cgSearch searchByGeocode(final cgBase base, String geocode, final String guid, final cgeoapplication app, final cgSearch search, final int reason, final CancellableHandler handler) { final Parameters params = new Parameters("decrypt", "y"); if (StringUtils.isNotBlank(geocode)) { params.put("wp", geocode); diff --git a/main/src/cgeo/geocaching/connector/IConnector.java b/main/src/cgeo/geocaching/connector/IConnector.java index 54962bb..89a94a1 100644 --- a/main/src/cgeo/geocaching/connector/IConnector.java +++ b/main/src/cgeo/geocaching/connector/IConnector.java @@ -4,8 +4,7 @@ import cgeo.geocaching.cgBase; import cgeo.geocaching.cgCache; import cgeo.geocaching.cgSearch; import cgeo.geocaching.cgeoapplication; - -import android.os.Handler; +import cgeo.geocaching.utils.CancellableHandler; public interface IConnector { /** @@ -76,5 +75,5 @@ public interface IConnector { */ public boolean supportsCachesAround(); - public cgSearch searchByGeocode(final cgBase base, final String geocode, final String guid, final cgeoapplication app, final cgSearch search, final int reason, final Handler handler); + public cgSearch searchByGeocode(final cgBase base, final String geocode, final String guid, final cgeoapplication app, final cgSearch search, final int reason, final CancellableHandler handler); } diff --git a/main/src/cgeo/geocaching/connector/opencaching/ApiOpenCachingConnector.java b/main/src/cgeo/geocaching/connector/opencaching/ApiOpenCachingConnector.java index 3c193d9..8660d2a 100644 --- a/main/src/cgeo/geocaching/connector/opencaching/ApiOpenCachingConnector.java +++ b/main/src/cgeo/geocaching/connector/opencaching/ApiOpenCachingConnector.java @@ -7,10 +7,9 @@ import cgeo.geocaching.cgCacheWrap; import cgeo.geocaching.cgSearch; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.connector.IConnector; +import cgeo.geocaching.utils.CancellableHandler; import cgeo.geocaching.utils.CryptUtils; -import android.os.Handler; - import java.util.List; public class ApiOpenCachingConnector extends OpenCachingConnector implements IConnector { @@ -38,7 +37,7 @@ public class ApiOpenCachingConnector extends OpenCachingConnector implements ICo } @Override - public cgSearch searchByGeocode(final cgBase base, final String geocode, final String guid, final cgeoapplication app, final cgSearch search, final int reason, final Handler handler) { + public cgSearch searchByGeocode(final cgBase base, final String geocode, final String guid, final cgeoapplication app, final cgSearch search, final int reason, final CancellableHandler handler) { final cgCache cache = OkapiClient.getCache(geocode); if (cache == null) { return null; diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java index 4c693a6..3d227b1 100644 --- a/main/src/cgeo/geocaching/maps/CGeoMap.java +++ b/main/src/cgeo/geocaching/maps/CGeoMap.java @@ -27,6 +27,7 @@ import cgeo.geocaching.maps.interfaces.MapFactory; import cgeo.geocaching.maps.interfaces.MapViewImpl; import cgeo.geocaching.maps.interfaces.OnDragListener; import cgeo.geocaching.maps.interfaces.OtherCachersOverlayItemImpl; +import cgeo.geocaching.utils.CancellableHandler; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -206,10 +207,11 @@ public class CGeoMap extends AbstractMap implements OnDragListener, ViewFactory } } }; - final private Handler loadDetailsHandler = new Handler() { + + final private class LoadDetailsHandler extends CancellableHandler { @Override - public void handleMessage(Message msg) { + public void handleRegularMessage(Message msg) { if (msg.what == 0) { if (waitDialog != null) { int secondsElapsed = (int) ((System.currentTimeMillis() - detailProgressTime) / 1000); @@ -243,6 +245,21 @@ public class CGeoMap extends AbstractMap implements OnDragListener, ViewFactory } } } + + @Override + public void handleCancel(final Object extra) { + if (loadDetailsThread != null) { + loadDetailsThread.stopIt(); + } + + if (geo == null) { + geo = app.startGeo(activity, geoUpdate, base, 0, 0); + } + if (Settings.isUseCompass() && dir == null) { + dir = app.startDir(activity, dirUpdate); + } + } + }; final private Handler noMapTokenHandler = new Handler() { @@ -617,9 +634,12 @@ public class CGeoMap extends AbstractMap implements OnDragListener, ViewFactory return true; } + final LoadDetailsHandler loadDetailsHandler = new LoadDetailsHandler(); + waitDialog = new ProgressDialog(activity); waitDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); waitDialog.setCancelable(true); + waitDialog.setCancelMessage(loadDetailsHandler.cancelMessage()); waitDialog.setMax(detailTotal); waitDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { @@ -1636,18 +1656,17 @@ public class CGeoMap extends AbstractMap implements OnDragListener, ViewFactory private class LoadDetails extends Thread { - private Handler handler = null; - private List<String> geocodes = null; - private volatile boolean stop = false; + final private CancellableHandler handler; + final private List<String> geocodes; private long last = 0L; - public LoadDetails(Handler handlerIn, List<String> geocodesIn) { - handler = handlerIn; - geocodes = geocodesIn; + public LoadDetails(final CancellableHandler handler, final List<String> geocodes) { + this.handler = handler; + this.geocodes = geocodes; } public void stopIt() { - stop = true; + handler.cancel(); } @Override @@ -1665,7 +1684,7 @@ public class CGeoMap extends AbstractMap implements OnDragListener, ViewFactory for (String geocode : geocodes) { try { - if (stop) { + if (handler.isCancelled()) { break; } @@ -1683,7 +1702,7 @@ public class CGeoMap extends AbstractMap implements OnDragListener, ViewFactory } } - if (stop) { + if (handler.isCancelled()) { Log.i(Settings.tag, "Stopped storing process."); break; @@ -1699,6 +1718,7 @@ public class CGeoMap extends AbstractMap implements OnDragListener, ViewFactory handler.sendEmptyMessage(0); } + // FIXME: what does this yield() do here? yield(); last = System.currentTimeMillis(); diff --git a/main/src/cgeo/geocaching/utils/CancellableHandler.java b/main/src/cgeo/geocaching/utils/CancellableHandler.java new file mode 100644 index 0000000..0b490d8 --- /dev/null +++ b/main/src/cgeo/geocaching/utils/CancellableHandler.java @@ -0,0 +1,112 @@ +package cgeo.geocaching.utils; + +import android.os.Handler; +import android.os.Message; + +/** + * Handler with a cancel policy. Once cancelled, the handler will not handle + * any more cancel or regular message. + */ +public abstract class CancellableHandler extends Handler { + + private boolean cancelled = false; + + private static class CancelHolder { + final Object payload; + + CancelHolder(final Object payload) { + this.payload = payload; + } + } + + @Override + final public void handleMessage(final Message message) { + if (cancelled) { + return; + } + + if (message.obj instanceof CancelHolder) { + cancelled = true; + handleCancel(((CancelHolder) message.obj).payload); + } else { + handleRegularMessage(message); + } + } + + /** + * Handle a non-cancel message.<br> + * Subclasses must implement this to handle messages. + * + * @param message + * the message to handle + */ + abstract protected void handleRegularMessage(final Message message); + + /** + * Handle a cancel message. + * + * @param extra + * the additional payload given by the canceller + */ + protected void handleCancel(final Object extra) { + } + + /** + * Get a cancel message that can later be sent to this handler to cancel it. + * + * @return a cancel message + */ + public Message cancelMessage() { + return cancelMessage(null); + } + + /** + * Get a cancel message with an additional parameter that can later be sent to + * this handler to cancel it. + * + * @param extra + * the extra parameter to give to the cancel handler + * @return a cancel message + */ + public Message cancelMessage(final Object extra) { + return this.obtainMessage(0, new CancelHolder(extra)); + } + + /** + * Cancel the current handler. This can be called from any thread. + */ + public void cancel() { + cancel(null); + } + + /** + * Cancel the current handler. This can be called from any thread. + * + * @param extra + * the extra parameter to give to the cancel handler + */ + public void cancel(final Object extra) { + cancelMessage(extra).sendToTarget(); + } + + /** + * Check if the current handler has been cancelled. + * + * @return true if the handler has been cancelled + */ + public boolean isCancelled() { + return cancelled; + } + + /** + * Check if a handler has been cancelled. + * + * @param handler + * a handler, or null + * @return true if the handler is not null and has been cancelled + */ + public static boolean isCancelled(final CancellableHandler handler) { + return handler != null && handler.isCancelled(); + } + +} |