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

Activity中CountDownTimer复用实现能否正确避免内存泄漏?

关于CountDownTimer复用与内存泄漏的疑问

我正在应用中实现倒计时功能,通过复用Activity中的对象,以上次停止时的剩余时间创建新CountDownTimer实例来恢复计时,担心会引发内存泄漏。以下是我的CountDownTimer实现代码,请问该实现是否能让垃圾回收器正确管理CountDownTimer,避免内存泄漏?

public class MyActivity extends AppCompatActivity {
    private CountDownTimer myCountDownTimer;
    private long timeRemaining = 20000;
    private TextView mTextField;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);

        mTextField = findViewById(R.id.textViewTimer);

        createTimer(timeRemaining);

        Button pauseButton = findViewById(R.id.pauseButton);
        pauseButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (myCountDownTimer != null) {
                    myCountDownTimer.cancel();
                }
            }
        });

        Button resumeButton = findViewById(R.id.resumeButton);
        resumeButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                createTimer(timeRemaining);
            }
        });
    }

    public void createTimer(long millisInFuture) {


        myCountDownTimer = new CountDownTimer(millisInFuture, 1000) {
            public void onTick(long millisUntilFinished) {
                mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
                timeRemaining = millisUntilFinished;
            }

            @Override
            public void onFinish() {
            }
        };

        myCountDownTimer.start();
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (myCountDownTimer != null) {
            myCountDownTimer.cancel();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (myCountDownTimer != null) {
            myCountDownTimer.cancel();
            myCountDownTimer = null;
        }
    }
}

你的实现不会引发内存泄漏,具体原因如下:

  • 每次暂停、页面销毁时都会调用cancel()终止Timer,onDestroy中还会把myCountDownTimer置为null,彻底切断Activity对Timer实例的引用
  • CountDownTimer内部的Handler在cancel()执行后会移除所有待处理的消息,不会再持有Timer实例的引用,也就不会间接持有Activity的引用
  • 虽然匿名内部类会持有外部Activity的引用,但只要Timer被正确终止且Activity的引用被切断,垃圾回收器就能正常回收这些对象

另外可以做个小优化:在createTimer方法里先取消已有的Timer,避免快速点击恢复按钮时创建多个Timer同时运行,修改后的代码如下:

public void createTimer(long millisInFuture) {
    // 先取消已存在的Timer实例
    if (myCountDownTimer != null) {
        myCountDownTimer.cancel();
    }
    myCountDownTimer = new CountDownTimer(millisInFuture, 1000) {
        public void onTick(long millisUntilFinished) {
            mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
            timeRemaining = millisUntilFinished;
        }

        @Override
        public void onFinish() {
        }
    };
    myCountDownTimer.start();
}

内容的提问来源于stack exchange,提问作者pequeñaluna

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 19:15:24