Handler机制应用之CountDownTimer篇

关于Handler的内部原理及实现可以查看——Handler机制源码之路

CountDownTimer 是系统提供的一个倒计时类。其内部就是使用了 Handler 封装的。

1. 用法

先来看一下如何使用。

// 源码注释
new CountDownTimer(30000, 1000) {

      public void onTick(long millisUntilFinished) {
         mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
     }
     
      public void onFinish() {
           mTextField.setText("done!");
     }
}.start();

可以看到,直接 new 一个 CountDownTimer 实例, 传入两个参数, 实现两个抽象方法onTick(long)onFinish(), 然后 start()

2. 源码

接下来通过源码+注释说明参数作用。

2.1 构造方法

/**
 * @param millisInFuture The number of millis in the future from the call
 *   to {@link #start()} until the countdown is done and {@link #onFinish()}
 *   is called.
 * @param countDownInterval The interval along the way to receive
 *   {@link #onTick(long)} callbacks.
 *   参数1 millisInfuture:这个参数代表你要倒计时的整体毫秒值,当start()开始执行时开始倒计时,当倒计时结束时回调onFinish()方法
 *   参数2 countDownInterval: 代表每次onTick(long)回调的时机,每countDownInterval差值回调一次
 */
public CountDownTimer(long millisInFuture, long countDownInterval) {
    mMillisInFuture = millisInFuture;
    mCountdownInterval = countDownInterval;
}

2.2 抽象方法

可以看到 onFinish()onTick(long) 方法为抽象方法,需要子类实现。

/**
 * Callback fired on regular interval.
 * @param millisUntilFinished The amount of time until finished.
 */
public abstract void onTick(long millisUntilFinished);

/**
 * Callback fired when the time is up.
 */
public abstract void onFinish();

2.3 start() 方法

/**
 * Start the countdown.
 */
public synchronized final CountDownTimer start() {
    mCancelled = false;
    if (mMillisInFuture <= 0) {// 如果开始的时候倒计时总时长未设置或为负数,直接结束。
        onFinish();
        return this;
    }
    mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;// 当前时间+总时间,等于要停止的实际时间
    // 通过Handler 发送消息,然后在Handler中真正开始计时
    mHandler.sendMessage(mHandler.obtainMessage(MSG));
    return this;
}

2.4 Handler 部分

// handles counting down
// 内部成员变量直接实例化,说明一个CountDownTimer对应一个Handler
private Handler mHandler = new Handler() {

    @Override
    public void handleMessage(Message msg) {

        synchronized (CountDownTimer.this) {// 这个锁我不知道为什么要加,我的理解在这个方法中一定是回调的同线程的Handler,Handler也没有声明成异步Handler,所以一定是按顺序回调
            if (mCancelled) {
                return;
            }

            final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();// 要停止的实际时间-当前时间,表示开始倒计时的总时长

            if (millisLeft <= 0) {
                onFinish();
            } else {
                long lastTickStart = SystemClock.elapsedRealtime();// 上次回调时间
                onTick(millisLeft);
                long lastTickDuration = SystemClock.elapsedRealtime() - lastTickStart;// 回调执行的时间
                long delay;
                if (millisLeft < mCountdownInterval) {// 需要倒计时的时间小于单次间隔
                    delay = millisLeft - lastTickDuration;
                    // 如果执行时间过长,会导致计时不准,这时直接进入下一次倒计时
                    if (delay < 0) delay = 0;
                } else {
                    delay = mCountdownInterval - lastTickDuration;

                    // special case: user's onTick took more than interval to
                    // complete, skip to next interval
                    while (delay < 0) delay += mCountdownInterval;
                }

                sendMessageDelayed(obtainMessage(MSG), delay);
            }
        }
    }
};

2.5 cancel() 方法

public synchronized final void cancel() {
    mCancelled = true;
    mHandler.removeMessages(MSG);
}

3. 总结

很简单的一个类,就是使用Handler封装的倒计时工具。需要注意的就是

  • CountDownTimer 创建的时候,一定要保证所在线程的 Looper 已经开启。
  • Activity 注销时,记着取消定时器。
  • 定时器中不要留存 Activity 的强引用。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容