anulowanie procesu handler.postdelayed

259

Używam, handler.postDelayed()aby utworzyć okres oczekiwania przed kolejnym etapem mojej aplikacji. Podczas okresu oczekiwania wyświetlam okno dialogowe z paskiem postępu i przyciskiem Anuluj .

Mój problem polega na tym, że nie mogę znaleźć sposobu na anulowanie zadania postDelayed przed upływem czasu.

Ron
źródło
Mam nadzieję, że ta pomoc gist.github.com/imammubin/a587192982ff8db221da14d094df6fb4 MainActivity jako Screen Launcher z funkcją obsługi i uruchamiania, Runnable, aby zalogować się na stronie lub karmić stronę z preferencją podstawową, logując się za pomocą firebase.
Mubin

Odpowiedzi:

479

Robię to, aby opublikować opóźnione uruchomienie:

myHandler.postDelayed(myRunnable, SPLASH_DISPLAY_LENGTH); 

I to, aby go usunąć: myHandler.removeCallbacks(myRunnable);

Varun
źródło
74
Jeśli możesz sobie pozwolić na anulowanie wszystkich wywołań zwrotnych i komunikatów w module obsługi i nie chcesz zachowywać odniesień do uruchamialnej, trzeci punkt w zaakceptowanej odpowiedzi na to pytanie jest inną alternatywą, która wydaje się działać w moim przypadku: stackoverflow. com / pytania / 11299440 /… (w zasadzie wywoływanie myHandler.removeCallbacksAndMessages (null);)
Mick
removeCallbacksAndMessages może załatwić sprawę, ale osobiście wolę mieć kontrolę nad zaplanowanymi uruchomieniami. Wystąpienie i obsługa pary Runnables nie zabije twoich aplikacji; w przeciwnym razie, jeśli potrzebujesz więcej niż dwóch lub trzech Runnables, możesz potrzebować czegoś mocniejszego, imho.
andrea.rinaldi
59

W przypadku, gdy masz wiele wewnętrznych / anonimowych plików runnables przekazanych do tego samego modułu obsługi i chcesz anulować wszystkie przy tym samym zdarzeniu

handler.removeCallbacksAndMessages(null);

Zgodnie z dokumentacją

Usuń wszystkie oczekujące posty oddzwonień i wysłane wiadomości, których obj jest tokenem. Jeśli token ma wartość NULL, wszystkie połączenia zwrotne i wiadomości zostaną usunięte.

Mani
źródło
Spowoduje to jednokrotne usunięcie wszystkich wywołań zwrotnych. W przeciwnym razie zadzwoń, removeCallbacks(callback) aby usunąć określone oddzwonienie
FindOutIslamNow
18

Innym sposobem jest obsłużenie samego Runnable:

Runnable r = new Runnable {
    public void run() {
        if (booleanCancelMember != false) {
            //do what you need
        }
    }
}
codeScriber
źródło
14
Czy booleanCancelMember nie musi być ostateczny, co oznacza, że ​​nie można go zmienić, a zatem jest bezużyteczny do tego celu?
stealthcopter
9
@stealthcopter nie, nie musi tak być.
Benoit Jadinon,
7
@pablisco Nie musi być ostateczny, nawet jeśli Runnable jest anonimowy. Może być członkiem klasy zamykającej.
Martin
6
Nie głosuj za tym, ale bądź ostrożny. Przy takim podejściu, jeśli wysłanie wielu Runnables jest opóźnione, możesz wpaść w nieprzyjemne warunki wyścigu. Nie anuluje to Runnable, więc to, czy ten kod zostanie wykonany, zależy od wartości booleanCancelMember w danym momencie dla każdego zaksięgowanego Runnable. Co może szybko stać się nieprzewidywalne.
Dennis K,
1
Jeśli Runnable NIE jest anonimowy, oznacza to, że mam do niego odwołanie ( rw tym przypadku), co oznacza, że ​​mogę użyć myHandler.removeCallbacks(r);. Jeśli Runnable jest anonimowy, flaga będzie członkiem klasy zamykającej, co oznacza, że ​​potrzebuję odwołania do tego obiektu, aby zmienić flagę, co oznacza, że ​​i tak będę musiał jeszcze mieć r, co oznacza, że ​​mogę myHandler.removeCallbacks(r);. A jeśli to robię, myHandler.removeCallbacks(r);taka flaga wcale nie jest konieczna. Czy coś brakuje?
nacho4d
1

Oto klasa zapewniająca metodę anulowania opóźnionego działania

public class DelayedAction {

private Handler _handler;
private Runnable _runnable;

/**
 * Constructor
 * @param runnable The runnable
 * @param delay The delay (in milli sec) to wait before running the runnable
 */
public DelayedAction(Runnable runnable, long delay) {
    _handler = new Handler(Looper.getMainLooper());
    _runnable = runnable;
    _handler.postDelayed(_runnable, delay);
}

/**
 * Cancel a runnable
 */
public void cancel() {
    if ( _handler == null || _runnable == null ) {
        return;
    }
    _handler.removeCallbacks(_runnable);
}}
Stéphane Padovani
źródło
0

Zadziałało dla mnie, gdy wywołałem CancelCallBacks (this) wewnątrz postu z opóźnieniem uruchomienia przez przekazanie go za pomocą wartości logicznej

Runnable runnable = new Runnable(){
    @Override
    public void run() {
        Log.e("HANDLER", "run: Outside Runnable");
        if (IsRecording) {
            Log.e("HANDLER", "run: Runnable");
            handler.postDelayed(this, 2000);
        }else{
            handler.removeCallbacks(this);
        }
    }
};
Ramin Fallahzadeh
źródło
3
W kodzie nie ma „CancelCallBacks”. Może dlatego, że nie istnieje? :)
Niesamowity