отмена процесса handler.postdelayed

259

Я использую, handler.postDelayed()чтобы создать период ожидания до следующего этапа моего приложения. В течение периода ожидания я отображаю диалог с индикатором выполнения и кнопкой отмены .

Моя проблема в том, что я не могу найти способ отменить задание postDelayed до истечения времени.

Рон
источник
Надеюсь, что эта справка поможет gist.github.com/imammubin/a587192982ff8db221da14d094df6fb4 MainActivity as Screen Launcher с обработчиком и функцией runable, Runnable запускает страницу входа в систему или страницу фида с базовым предпочтением пользователя входа в систему с firebase.
Мубин

Ответы:

479

Я делаю это для публикации отложенного запуска:

myHandler.postDelayed(myRunnable, SPLASH_DISPLAY_LENGTH); 

И это, чтобы удалить это: myHandler.removeCallbacks(myRunnable);

Варуна
источник
74
Если вы можете позволить себе отменить все обратные вызовы и сообщения в обработчике и не хотите хранить ссылки на исполняемый файл, третья точка в принятом ответе на этот вопрос - это еще одна альтернатива, которая в любом случае работает для моего случая: stackoverflow. com / questions / 11299440 /… (по сути, вызывая myHandler.removeCallbacksAndMessages (null);)
Мик
removeCallbacksAndMessages может сделать свое дело, но лично я предпочитаю иметь контроль над запланированными runnables. Создание и обработка пары Runnables не убьет производительность вашего приложения; в противном случае, если вам нужно более двух или трех Runnables, вам может понадобиться что-то более мощное, imho.
andrea.rinaldi
59

Если у вас есть несколько внутренних / анонимных исполняемых модулей, переданных одному и тому же обработчику, и вы хотите отменить все при одном и том же событии

handler.removeCallbacksAndMessages(null);

Согласно документации,

Удалите все ожидающие сообщения обратных вызовов и отправленные сообщения, чей объект является токеном. Если токен нулевой, все обратные вызовы и сообщения будут удалены.

Mani
источник
Это удалит все выполняемые обратные вызовы один раз. В противном случае позвоните, removeCallbacks(callback) чтобы удалить конкретный обратный вызов
FindOutIslamNow
18

Другой способ - обработать сам Runnable:

Runnable r = new Runnable {
    public void run() {
        if (booleanCancelMember != false) {
            //do what you need
        }
    }
}
codeScriber
источник
14
Разве booleanCancelMember не должен быть окончательным, что означает, что он не может быть изменен и, следовательно, бесполезен для этой цели?
стелскоптер
9
@stealthcopter нет, это не должно быть.
Бенуа Джадинон
7
@pablisco Это не должно быть окончательным, даже если Runnable является анонимным. Это может быть член во включающем классе.
Мартин,
6
Не опровергайте это, но будьте осторожны. При таком подходе, если несколько Runnables публикуются с задержкой, вы можете столкнуться с неприятными условиями гонки. Это не отменяет Runnable, поэтому будет ли выполняться этот код, зависит от значения booleanCancelMember в конкретный момент для каждого опубликованного Runnable. Который может быстро стать непредсказуемым.
Деннис К
1
Если Runnable НЕ анонимный, это означает, что у меня есть ссылка на него ( rв данном случае), что означает, что я могу использовать myHandler.removeCallbacks(r);. Если Runnable является анонимным, то флаг будет членом входящего в него класса, что означает, что мне нужна ссылка на этот объект для изменения флага, что означает, что мне снова нужно будет в rлюбом случае, что означает, что я могу это сделать myHandler.removeCallbacks(r);. И если я делаю, myHandler.removeCallbacks(r);то такой флаг вообще не нужен. Я что-то упускаю?
nacho4d
1

Вот класс, предоставляющий метод отмены для отложенного действия

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);
}}
Стефан Падовани
источник
0

Это сработало для меня, когда я вызвал CancelCallBacks (this) внутри отложенного запуска, передавая его через логическое значение

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);
        }
    }
};
Рамин Фаллахзаде
источник
3
В вашем коде нет "CancelCallBacks". Может потому что его не существует? :)
Невероятный
-1

Надеюсь, что эта суть поможет https://gist.github.com/imammubin/a587192982ff8db221da14d094df6fb4

MainActivity как Screen Launcher с обработчиком и запускаемой функцией, Runnable запускается для входа на страницу или на страницу канала с базовыми предпочтениями для входа в систему пользователя с помощью firebase.

Мубин
источник