membatalkan proses handler.postdelayed

259

Saya menggunakan handler.postDelayed()untuk membuat masa tunggu sebelum tahap selanjutnya dari aplikasi saya berlangsung. Selama masa tunggu saya menampilkan dialog dengan progress bar dan tombol batal .

Masalah saya adalah saya tidak dapat menemukan cara untuk membatalkan tugas postDelay sebelum waktu berlalu.

Ron
sumber
Semoga bantuan inti ini gist.github.com/imammubin/a587192982ff8db221da14d094df6fb4 MainActivity sebagai Screen Launcher dengan fungsi handler & runable, runnable run untuk masuk ke halaman atau halaman feed dengan pengguna login preferensi dasar dengan firebase.
Mubin

Jawaban:

479

Saya melakukan ini untuk mengirim runnable yang tertunda:

myHandler.postDelayed(myRunnable, SPLASH_DISPLAY_LENGTH); 

Dan ini untuk menghapusnya: myHandler.removeCallbacks(myRunnable);

Varun
sumber
74
Jika Anda mampu untuk membatalkan semua panggilan balik dan pesan pada handler dan tidak ingin harus menyimpan referensi ke runnable, poin ketiga dalam jawaban yang diterima untuk pertanyaan ini adalah alternatif lain yang tampaknya bekerja untuk kasus saya: stackoverflow. com / pertanyaan / 11299440 / ... (pada dasarnya memanggil myHandler.removeCallbacksAndMessages (null);)
Mick
removeCallbacksAndMessages dapat melakukan trik, tetapi secara pribadi saya lebih suka memiliki kontrol atas runnables yang dijadwalkan. Memasang dan menangani sepasang Runnables tidak akan membunuh kinerja aplikasi Anda; jika tidak, jika Anda membutuhkan lebih dari dua atau tiga Runnables, Anda mungkin memerlukan sesuatu yang lebih kuat, imho.
andrea.rinaldi
59

Jika Anda memiliki beberapa runnables internal / anonim yang diteruskan ke handler yang sama, dan Anda ingin membatalkan semua penggunaan acara yang sama

handler.removeCallbacksAndMessages(null);

Sesuai dokumentasi,

Hapus posting panggilan balik yang ditangguhkan dan pesan terkirim yang keberatannya token. Jika token adalah null, semua panggilan balik dan pesan akan dihapus.

Mani
sumber
Ini akan menghapus semua panggilan balik yang bisa dijalankan sekali. Kalau tidak, panggil removeCallbacks(callback) untuk menghapus callback tertentu
FindOutIslamNow
18

Cara lain adalah dengan menangani Runnable itu sendiri:

Runnable r = new Runnable {
    public void run() {
        if (booleanCancelMember != false) {
            //do what you need
        }
    }
}
codeScriber
sumber
14
Bukankah booleanCancelMember harus final, yang berarti tidak bisa diubah dan dengan demikian tidak berguna untuk tujuan ini?
stealthcopter
9
@stealthcopter tidak tidak harus.
Benoit Jadinon
7
@pablisco Tidak harus final meskipun Runnable bersifat anonim. Itu bisa menjadi anggota di kelas terlampir.
Martin
6
Bukan downvoting ini, tapi hati-hati. Dengan pendekatan ini, jika beberapa Runnable diposting tertunda, Anda dapat mengalami kondisi balapan yang tidak menyenangkan. Ini tidak membatalkan Runnable, jadi apakah kode itu akan dieksekusi atau tidak tergantung pada nilai booleanCancelMember pada saat tertentu untuk setiap Runnable yang diposting. Yang mungkin dengan cepat menjadi tidak terduga.
Dennis K
1
Jika Runnable BUKAN anonim itu berarti saya memiliki referensi untuk itu ( rdalam hal ini) yang berarti saya dapat menggunakan myHandler.removeCallbacks(r);. Jika Runnable anonim maka flag akan menjadi anggota di kelas terlampir, yang berarti saya perlu referensi ke objek itu untuk mengubah flag, yang berarti saya lagi harus memiliki ranyways, yang berarti saya bisa melakukannya myHandler.removeCallbacks(r);. Dan jika saya lakukan myHandler.removeCallbacks(r);maka bendera seperti itu tidak perlu sama sekali. Apakah saya melewatkan sesuatu?
nacho4d
1

Ini adalah kelas yang menyediakan metode pembatalan untuk tindakan yang tertunda

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

Ini bekerja untuk saya ketika saya menelepon CancelCallBacks (ini) di dalam post tertunda runnable dengan menyerahkannya melalui boolean

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
sumber
3
Tidak ada "CancelCallBacks" dalam kode Anda. Mungkin karena itu tidak ada? :)
1 Jan