Android Studio中CountDownTimer无法取消,任务完成仍推送通知
问题分析与修复方案
核心问题
你的代码存在两个关键问题,导致任务标记完成后仍会推送通知:
- 所有任务共用同一个
countDownTimer实例,标记单个任务完成时,只能取消当前活跃的定时器,之前启动的其他任务定时器还在后台运行,到时间就会触发通知。 setTasks方法会无条件启动定时器,哪怕列表里有已完成的任务,也会错误启动定时器。
具体修复步骤
1. 给每个任务分配独立定时器
修改ToDoModel类,添加专属的CountDownTimer成员变量,让每个任务的定时器互不干扰:
public class ToDoModel { // 原有成员变量 private int id; private int status; private long timeLeftInMilliseconds; // 添加定时器变量 private CountDownTimer countDownTimer; // 对应的getter和setter方法 public CountDownTimer getCountDownTimer() { return countDownTimer; } public void setCountDownTimer(CountDownTimer countDownTimer) { this.countDownTimer = countDownTimer; } public long getTimeLeftInMilliseconds() { return timeLeftInMilliseconds; } public void setTimeLeftInMilliseconds(long timeLeftInMilliseconds) { this.timeLeftInMilliseconds = timeLeftInMilliseconds; } public int getStatus() { return status; } }
2. 修改定时器启停方法,针对单个任务操作
调整方法逻辑,让每个任务的定时器单独启停:
// 启动单个任务的定时器 public void Reminder_startTimer(ToDoModel item) { // 先停止已有定时器,避免重复启动 if (item.getCountDownTimer() != null) { item.getCountDownTimer().cancel(); } CountDownTimer timer = new CountDownTimer(item.getTimeLeftInMilliseconds(), 1000) { @Override public void onTick(long l) { // 更新任务剩余时间到模型中 item.setTimeLeftInMilliseconds(l); } @Override public void onFinish() { // 额外检查任务状态,避免推送已完成任务的通知 if (item.getStatus() != 1) { activity.makeNotification(); } } }.start(); item.setCountDownTimer(timer); } // 停止单个任务的定时器 public void Reminder_stopTimer(ToDoModel item) { if (item.getCountDownTimer() != null) { item.getCountDownTimer().cancel(); item.setCountDownTimer(null); // 清空引用,防止内存泄漏 } }
3. 修正复选框状态变化逻辑
确保标记任务完成/未完成时,操作的是当前任务的定时器:
@Override public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) { if(isChecked){ myDB.updateStatus(item.getId(), 1); Reminder_stopTimer(item); // 停止当前任务的定时器 }else{ myDB.updateStatus(item.getId(), 0); Reminder_startTimer(item); // 启动当前任务的定时器 } }
4. 修复列表初始化逻辑,只给未完成任务启动定时器
public void setTasks(List<ToDoModel> mList){ this.mList = mList; notifyDataSetChanged(); // 遍历列表,仅给未完成(status=0)的任务启动定时器 for (ToDoModel item : mList) { if (item.getStatus() == 0) { Reminder_startTimer(item); } } }
5. 删除任务时先停止定时器
public void deleteTask(int position){ ToDoModel item = mList.get(position); Reminder_stopTimer(item); // 先停止任务的定时器 myDB.deleteTask(item.getId()); mList.remove(position); notifyItemRemoved(position); }
内容的提问来源于stack exchange,提问作者Avenger
相关产品推荐
相关产品推荐

