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
相关产品推荐
相关产品推荐

