Bạn lên lịch đổi nhãn sau một giây rồi muốn hủy khi người dùng bấm nút. Hai lambda chứa cùng câu lệnh trông giống nhau, nhưng việc tạo một Runnable mới lúc hủy không thay thế tham chiếu đã dùng khi đặt lịch. Cách dễ review là giữ callback trong một biến và dùng biến đó cho cả hai thao tác.
Tách callback khỏi hai nút
Ví dụ sau là đoạn tích hợp trong Activity Kotlin có TextView tên statusView và hai nút scheduleButton, cancelButton đã được gán. Thêm đoạn này vào bước gắn listener sau khi View đã tồn tại. Các nút gọi trên main thread; tác vụ chỉ đổi nhãn và không thực hiện I/O.
val handler = Handler(Looper.getMainLooper())
val showResult = Runnable {
statusView.text = "Đã chạy"
}
scheduleButton.setOnClickListener {
handler.removeCallbacks(showResult)
val queued = handler.postDelayed(showResult, 1000L)
statusView.text = if (queued) "Đang chờ" else "Không xếp được"
}
cancelButton.setOnClickListener {
handler.removeCallbacks(showResult)
statusView.text = "Đã yêu cầu hủy"
}
Import Handler và Looper từ android.os. Lệnh remove trước khi post khiến bấm đặt lịch lần nữa thay thế callback còn chờ. Giá trị trả về từ postDelayed cho biết có xếp được việc hay không. Nó không cho biết dòng đổi nhãn đã chạy. Nhãn trên nút hủy dùng chữ “yêu cầu” vì hàm hủy không trả số callback bị loại.
Phạm vi hủy
Tài liệu Android mô tả removeCallbacks với Runnable từ API level 1. Nó loại các lần đăng callback tương ứng còn chờ trong queue của Handler đó. Không dùng nó để dừng một hàm đã bắt đầu chạy hoặc một request mạng đã được hàm khởi tạo. Công việc bất đồng bộ cần cơ chế hủy và xử lý kết quả đến muộn của riêng nó.
Đừng gọi removeCallbacksAndMessages với null trên một Handler dùng chung chỉ để hủy một nhãn. Phạm vi của thao tác đó rộng hơn callback đang xét. Nếu callback giữ tham chiếu View, lưu cùng tham chiếu ở nơi sở hữu vòng đời và dọn nó khi View không còn dùng được. Trong Fragment, hãy chọn vòng đời View thay vì giả định mọi View sống đến lúc Fragment bị hủy.
Kiểm tra trên dự án
Thử đặt lịch rồi hủy ngay: nhãn không nên chuyển thành “Đã chạy” từ lần chờ đó. Thử đặt hai lần cách nhau ngắn để kiểm tra lượt trước được thay thế. Sau đó để một lần chạy xong rồi bấm hủy, nhằm phân biệt hủy phần còn chờ với hoàn tác kết quả. Lặp lại khi rời màn hình và kiểm tra dọn callback tại đúng vòng đời.
Đây là kế hoạch kiểm tra theo API được đọc ngày 12/11/2026; chưa biên dịch Kotlin, chạy Android SDK hoặc đo thời gian trên thiết bị. Một giây là cấu hình demo, không phải cam kết thời điểm chính xác.
Kết luận
Giữ đúng Runnable, dùng cùng Handler và chỉ kỳ vọng hủy việc còn chờ. Xử lý vòng đời và công việc đã bắt đầu bằng cơ chế phù hợp với từng loại tác vụ.


