编程语言
首页 > 编程语言> > CountDownTimer源码解析

CountDownTimer源码解析

作者:互联网

CountDownTimer适用于做倒计时,时间间隔一样的任务,比如5秒上传一次经纬度,这次我们看看它的源码。

1.初始化

            countDownTimer = object : CountDownTimer(Long.MAX_VALUE, 1000) {
                override fun onFinish() {}
                override fun onTick(millisUntilFinished: Long) {
                    tv.text = millisUntilFinished.toString()
                }
            }

我们先看看这两个传参,第一个意思是 倒计时的总秒数,间隔时间

    public CountDownTimer(long millisInFuture, long countDownInterval) {
        mMillisInFuture = millisInFuture;
        mCountdownInterval = countDownInterval;
    }

 

2.启动

如果我们当初传 倒计时总秒数为0,就会直接走 onFinish,结束了此次倒计时。

最后给handler发送一个消息,这里说明这里倒计时是由Handler完成,看来间隔时间不会那么精准,甚至可能因为Handler消息过多而卡住。

    public synchronized final CountDownTimer start() {
        mCancelled = false;
        if (mMillisInFuture <= 0) {
            onFinish();
            return this;
        }
//算出结束倒计时的时间戳。
        mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
        mHandler.sendMessage(mHandler.obtainMessage(MSG));
        return this;
    }

我们看看这个Handler的代码


    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 {
//执行任务之前的时间戳
                    long lastTickStart = SystemClock.elapsedRealtime();
//触发一次间隔
                    onTick(millisLeft);
//onTick执行时间
                    long lastTickDuration = SystemClock.elapsedRealtime() - lastTickStart;
//延迟时间
                    long delay;
//如果剩余时间小于间隔时间,则是设置延迟时间为  剩余时间 减去 onTick执行时间
                    if (millisLeft < mCountdownInterval) {
                        delay = millisLeft - lastTickDuration;
                        if (delay < 0) delay = 0;
                    } else {
//若大于,延迟时间设置为 间隔时间减去onTick执行时间,这里算是在修正误差
                        delay = mCountdownInterval - lastTickDuration;
                        while (delay < 0) delay += mCountdownInterval;
                    }
//发送延迟消息,为下一次间隔任务做准备
                    sendMessageDelayed(obtainMessage(MSG), delay);
                }
            }
        }
    };

 

3.取消

就是清除消息,并设置mCancelled 为true,使还没有执行onTick的消息停止运行

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

4.总结

CountDownTimer主要使用Handler来完成时间间隔的计算,通过 计算onTick的执行时间,来去除误差,但是如果Handler本身Looper循环卡了,间隔任务还是会卡住

标签:synchronized,mCancelled,public,倒计时,Handler,解析,源码,CountDownTimer
来源: https://blog.csdn.net/z979451341/article/details/115175946