安卓倒计时利器:CountDownTimer的使用

QuibblerQuibbler 2025-10-29 约 13 分钟 880 次阅读

安卓倒计时利器:CountDownTimer的使用

CountDownTimer是Android框架中自带中的一个类,用于实现倒计时功能。通过CountDownTimer类,可以创建一个倒计时器,指定总倒计时时间以及每次倒计时的间隔时间。一旦倒计时开始,CountDownTimer会在指定的间隔时间内执行操作,直到倒计时结束。

CountDownTimer是一个抽象类:CountDownTimer(long millisInFuture, long countDownInterval),millisInFuture: 表示总的倒计时时间,以毫秒为单位。在倒计时结束之前,倒计时器将一直执行。countDownInterval: 表示倒计时的间隔时间,以毫秒为单位。每隔这个时间间隔,onTick()方法将会被调用一次。

public abstract class CountDownTimer {
        private final long mMillisInFuture;
        private final long mCountdownInterval;
        private long mStopTimeInFuture;
 
        private boolean mCancelled = false;
    
        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;
        }    
        ...
    }

包装了两个抽象方法onTick()和onFinish(),通常在使用的时候继承自CountDownTimer实现onTick和onFinish这两个抽象方法。

public abstract class CountDownTimer {
        ...
        public abstract void onTick(long millisUntilFinished);
        public abstract void onFinish();
        ...
    }

onTick(long millisUntilFinished):在每次倒计时间隔结束时调用,用于执行更新UI等操作。millisUntilFinished: 表示距离倒计时结束还有多少时间,以毫秒为单位。

onFinish():在倒计时结束时调用,用于执行最终的操作。

start():启动倒计时器,开始执行倒计时。

cancel():取消倒计时器,停止倒计时的执行。

CountDownTimer是基于Handler实现的,内部封装了Handler,这里使用默认的无参构造方式创建Handler

@Deprecated
    public Handler() {
        this(null, false);
    }

在之前的创建Handler的几种方法一文中,我们可以知道,默认用当前线程的Looper创建Handler,一般为主线程,如果在没有Looper的线程中创建Handler则会抛出异常。

public Handler(@Nullable Callback callback, boolean async) {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
        mIsShared = false;
    }

无需自己切线程,回调运行在创建CountDownTimer对象的线程上,一般为主线程,也可能是HandlerThread等其它带Looper的子线程中。

public abstract class CountDownTimer {
        .
        // handles counting down
        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);
                        // take into account user's onTick taking time to execute
                        long lastTickDuration = SystemClock.elapsedRealtime() - lastTickStart;
                        long delay;
                        if (millisLeft < mCountdownInterval) {
                            // just delay until done
                            delay = millisLeft - lastTickDuration;
                            // special case: user's onTick took more than interval to
                            // complete, trigger onFinish without delay
                            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);
                    }
                }
            }
        };
    }

创建多个CountDownTimer时每个实例拥有独立的锁、独立的Handler消息队列,彼此完全并行,不会出现锁等待。

CountDownTimer的优点是官方、简洁、内部维护Handler实现倒计时,对于90%的场景足够用了。缺点也有:无暂停接口。如果需要暂停/恢复可以考虑结合协程封装。

相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w