cancelar un proceso handler.postdelayed

259

Estoy usando handler.postDelayed()para crear un período de espera antes de que tenga lugar la siguiente etapa de mi aplicación. Durante el período de espera, estoy mostrando un cuadro de diálogo con la barra de progreso y el botón de cancelar .

Mi problema es que no puedo encontrar una manera de cancelar la tarea postDelayed antes de que transcurra el tiempo.

Ron
fuente
Espero que este gist ayude gist.github.com/imammubin/a587192982ff8db221da14d094df6fb4 MainActivity como Screen Launcher con controlador y función ejecutable, Runnable run to login page o feed page con base de preferencia de inicio de sesión de usuario con firebase.
Mubin

Respuestas:

479

Hago esto para publicar un runnable retrasado:

myHandler.postDelayed(myRunnable, SPLASH_DISPLAY_LENGTH); 

Y esto para eliminarlo: myHandler.removeCallbacks(myRunnable);

Varun
fuente
74
Si puede permitirse el lujo de cancelar todas las devoluciones de llamada y mensajes en el controlador y no quiere tener que mantener referencias a lo ejecutable, el tercer punto en la respuesta aceptada a esta pregunta es otra alternativa que parece funcionar para mi caso de todos modos: stackoverflow. com / preguntas / 11299440 /… (esencialmente llamando a myHandler.removeCallbacksAndMessages (null);)
Mick
removeCallbacksAndMessages puede hacer el truco, pero personalmente prefiero tener el control sobre los ejecutables programados. Instalar y manejar un par de Runnables no matará el rendimiento de la aplicación; de lo contrario, si necesita más de dos o tres Runnables, es posible que necesite algo más poderoso, en mi humilde opinión.
andrea.rinaldi
59

En caso de que tenga múltiples ejecutables internos / anónimos pasados ​​al mismo controlador, y desee cancelar todos en el mismo evento, use

handler.removeCallbacksAndMessages(null);

Según la documentación,

Elimine cualquier publicación pendiente de devoluciones de llamada y mensajes enviados cuyo obj es token. Si el token es nulo, se eliminarán todas las devoluciones de llamada y mensajes.

Mani
fuente
Esto eliminará todas las devoluciones de llamada ejecutables una vez. De lo contrario, llame removeCallbacks(callback) para eliminar la devolución de llamada específica
FindOutIslamNow
18

Otra forma es manejar el Runnable mismo:

Runnable r = new Runnable {
    public void run() {
        if (booleanCancelMember != false) {
            //do what you need
        }
    }
}
codeScriber
fuente
14
¿No tendría que ser booleanCancelMember final, lo que significa que no se puede cambiar y, por lo tanto, es inútil para este propósito?
stealthcopter
9
@stealthcopter no, no tiene que ser así.
Benoit Jadinon
77
@pablisco No tiene que ser definitivo incluso si Runnable es anónimo. Puede ser un miembro de la clase adjunta.
Martin
66
No desestimando esto, pero ten cuidado. Con este enfoque, si se publican múltiples Runnables con retraso, puede correr en condiciones de carrera desagradables. Esto no cancela el Runnable, por lo que si ese código se ejecutará o no depende del valor de booleanCancelMember en el momento específico para cada Runnable publicado. Lo que puede volverse impredecible rápidamente.
Dennis K
1
Si el Runnable NO es anónimo, significa que tengo una referencia ( ren este caso), lo que significa que puedo usarlo myHandler.removeCallbacks(r);. Si el Runnable es anónimo, la bandera será un miembro de la clase adjunta, lo que significa que necesito una referencia a ese objeto para cambiar la bandera, lo que significa que nuevamente tendré que tener r, lo que significa que puedo hacerlo myHandler.removeCallbacks(r);. Y si lo estoy haciendo myHandler.removeCallbacks(r);, tal bandera no es necesaria en absoluto. ¿Me estoy perdiendo de algo?
nacho4d
1

Aquí hay una clase que proporciona un método de cancelación para una acción retrasada

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

Funcionó para mí cuando llamé a CancelCallBacks (esto) dentro de la publicación demorada ejecutable al entregarla a través de un 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
fuente
3
No hay "CancelCallBacks" en su código. Tal vez porque no existe? :)
El increíble Jan