You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio中CountDownTimer无法取消,任务完成仍推送通知

问题分析与修复方案

核心问题

你的代码存在两个关键问题,导致任务标记完成后仍会推送通知:

  1. 所有任务共用同一个countDownTimer实例,标记单个任务完成时,只能取消当前活跃的定时器,之前启动的其他任务定时器还在后台运行,到时间就会触发通知。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 22:43:16