1、API
1
| CountDownTimer (long millisInFuture, long countDownInterval)
|
参数1,设置倒计时的总时间(毫秒)
参数2,设置每次减去多少毫秒
2、基本用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| private Button btn;
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); btn.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) { timer.start(); } }); } private CountDownTimer timer = new CountDownTimer(60000, 1000) {
@Override public void onTick(long millisUntilFinished) { btn.setText((millisUntilFinished / 1000) + "秒后可重发"); }
@Override public void onFinish() { btn.setText("重新获取"); } };
@Override protected void onDestroy() { super.onDestroy(); if (timer != null){ timer.cancel(); } }
|
3、存在的问题
注意onDestroy() ,不然会存在内存泄漏的问题,源码很简单:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| package android.os;
public abstract class CountDownTimer {
public CountDownTimer(long millisInFuture, long countDownInterval) { mMillisInFuture = millisInFuture; mCountdownInterval = countDownInterval; }
public synchronized final void cancel() { mCancelled = true; mHandler.removeMessages(MSG); }
public synchronized final CountDownTimer start() { mCancelled = false; if (mMillisInFuture <= 0) { onFinish(); return this; } mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture; mHandler.sendMessage(mHandler.obtainMessage(MSG)); return this; }
.......
private Handler mHandler = new Handler() {
@Override public void handleMessage(Message msg) {
synchronized (CountDownTimer.this) { if (mCancelled) { return; }
final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
if (millisLeft <= 0) { onFinish(); } else if (millisLeft < mCountdownInterval) { sendMessageDelayed(obtainMessage(MSG), millisLeft); } else { long lastTickStart = SystemClock.elapsedRealtime(); onTick(millisLeft);
long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();
while (delay < 0) delay += mCountdownInterval;
sendMessageDelayed(obtainMessage(MSG), delay); } } } }; }
|
从源码中可以看出,CountDownTimer的内部实现是采用Handler机制,通过sendMessageDelayed延迟发送一条message到主线程的looper中,然后在自身中收到之后判断剩余时间,并发出相关回调,然后再次发出message的方式。
如果在Activity或者Fragment被回收时并未调用CountDownTimer的cancel()方法结束自己,这个时候CountDownTimer的Handler方法中如果判断到当前的时间未走完,那么会继续调用sendMessageDelayed(obtainMessage(MSG), delay);
触发onTick(millisLeft);
,当回调了Activity或者fragment中CountDownTimer的onTick方法时,Activity或者Fragment已经被系统回收,从而里面的变量被设置为null,再调用btn.setText((millisUntilFinished / 1000) + "秒后可重发");
btn为空,也就空指针了,而CountDownTimer中的Handler方法还在继续执行,这一块空间始终无法被系统回收也就造成了内存泄漏问题。