cancelando um processo handler.postdelayed

259

estou usando handler.postDelayed() para criar um período de espera antes do próximo estágio do meu aplicativo. Durante o período de espera, estou exibindo uma caixa de diálogo com barra de progresso e botão Cancelar .

Meu problema é que não consigo encontrar uma maneira de cancelar a tarefa postDelayed antes que o tempo se esgote.

Ron
fonte
Espero que este gist ajude gist.github.com/imammubin/a587192982ff8db221da14d094df6fb4 MainActivity como iniciador de tela com manipulador e função executável, o Runnable run to login page ou feed page with user login preferencial base com firebase.
Mubin 12/01/19

Respostas:

479

Eu faço isso para postar um executável atrasado:

myHandler.postDelayed(myRunnable, SPLASH_DISPLAY_LENGTH); 

E isso para removê-lo: myHandler.removeCallbacks(myRunnable);

Varun
fonte
74
Se você puder cancelar todos os retornos de chamada e mensagens no manipulador e não desejar manter as referências ao executável, o terceiro ponto na resposta aceita a essa pergunta é outra alternativa que parece funcionar para o meu caso: stackoverflow. com / questions / 11299440 /… (essencialmente chamando myHandler.removeCallbacksAndMessages (null);)
Mick
removeCallbacksAndMessages pode fazer o truque, mas pessoalmente prefiro ter o controle sobre as executáveis ​​agendadas. Instalar e manipular um par de Runnables não prejudica o desempenho do aplicativo; caso contrário, se você precisar de mais de dois ou três Runnables, poderá precisar de algo mais poderoso, imho.
226156 Andrey.rinaldi 13/07/2015
59

Caso você tenha várias executáveis ​​internas / anônimas passadas para o mesmo manipulador e deseje cancelar todas no mesmo evento de uso

handler.removeCallbacksAndMessages(null);

Conforme documentação,

Remova quaisquer postagens pendentes de retornos de chamada e mensagens enviadas cujo objetivo seja um token. Se o token for nulo, todos os retornos de chamada e mensagens serão removidos.

Mani
fonte
Isso removerá todos os retornos de chamada executáveis ​​uma vez. Caso contrário, ligue removeCallbacks(callback) para remover retorno de chamada específico
FindOutIslamNow
18

Outra maneira é lidar com o próprio Runnable:

Runnable r = new Runnable {
    public void run() {
        if (booleanCancelMember != false) {
            //do what you need
        }
    }
}
codeScriber
fonte
14
O booleanCancelMember não teria que ser final, o que significa que não poderia ser alterado e, portanto, inútil para esse fim?
Stealthcopter
9
@ stealthcopter não, não precisa ser.
Benoit Jadinon
7
@pablisco Não precisa ser final, mesmo que o Runnable seja anônimo. Pode ser um membro da classe anexa.
Martin
6
Não diminuindo o voto, mas tenha cuidado. Com essa abordagem, se várias Runnables forem postadas atrasadas, você poderá enfrentar condições desagradáveis ​​de corrida. Isso não cancela o Runnable, portanto, se esse código será executado ou não, depende do valor de booleanCancelMember no momento específico de cada Runnable publicado. O que pode rapidamente se tornar imprevisível.
Dennis K
1
Se o Runnable NÃO for anônimo, significa que tenho uma referência a ele ( rneste caso), o que significa que posso usar myHandler.removeCallbacks(r);. Se o Runnable for anônimo, o sinalizador será um membro da classe anexa, o que significa que eu preciso de uma referência a esse objeto para alterar o sinalizador, o que significa que eu novamente precisarei ter de rqualquer maneira, o que significa que posso fazer myHandler.removeCallbacks(r);. E se estou fazendo myHandler.removeCallbacks(r);, essa bandeira não é necessária. Estou esquecendo de algo?
N
1

Aqui está uma classe que fornece um método de cancelamento para uma ação atrasada

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
fonte
0

Funcionou para mim quando eu chamei CancelCallBacks (this) dentro do post atrasado, executável, entregando-o através de um valor booleano

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
fonte
3
Não há "CancelCallBacks" no seu código. Talvez porque não existe? :)
O incrível Jan