美文网首页
Handler机制应用之CountDownTimer篇

Handler机制应用之CountDownTimer篇

作者: 烤地瓜次不次 | 来源:发表于2019-03-08 13:06 被阅读0次

    关于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 的强引用。

    相关文章

      网友评论

          本文标题:Handler机制应用之CountDownTimer篇

          本文链接:https://www.haomeiwen.com/subject/vkkrpqtx.html