aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching/utils/CancellableHandler.java
blob: d4915eb8d8cbb968a2d78ff41c90051c4b0a5cab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
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 volatile 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();
    }

}