当前位置:   article > 正文

安卓CountDownTimer的使用

countdowntimer


一、简介

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

1.1 CountDownTimer简介

CountDownTimer 是一个抽象类,包装了两个抽象方法onTick()和onFinish(),通常在使用的时候继承自CountDownTimer实现这两个抽象方法,内部封装了Handler,CountDownTimer是基于Handler实现的。

public abstract class CountDownTimer {

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

    /**
     * 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();
    ......
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

1.2 常用API

  • CountDownTimer(long millisInFuture, long countDownInterval)
    millisInFuture: 表示总的倒计时时间,以毫秒为单位。在倒计时结束之前,倒计时器将一直执行。
    countDownInterval: 表示倒计时的间隔时间,以毫秒为单位。每隔这个时间间隔,onTick方法将会被调用一次。
  • start():
    作用:启动倒计时器,开始执行倒计时。
    示例:countDownTimer.start();
  • cancel():
    作用:取消倒计时器,停止倒计时的执行。
    示例:countDownTimer.cancel();
  • onTick(long millisUntilFinished):
    作用:在每次倒计时间隔结束时调用,用于执行更新UI等操作。
    millisUntilFinished: 表示距离倒计时结束还有多少时间,以毫秒为单位。
    示例:
    new CountDownTimer(60000, 1000) {
    public void onTick(long millisUntilFinished) {
    textView.setText("Seconds remaining: " + millisUntilFinished / 1000);
    }
    public void onFinish() {
    textView.setText(“Done!”);
    }
    }.start();
  • onFinish():
    作用:在倒计时结束时调用,用于执行最终的操作。
    示例:
    new CountDownTimer(60000, 1000) {
    public void onTick(long millisUntilFinished) {
    // Do something on tick
    }
    public void onFinish() {
    textView.setText(“Done!”);
    }
    }.start();

二、CountDownTimer的用法

2.1 主线程中使用

Oncreate里使用

    public static void test5() {
        CountDownTimer countDownTimer = new CountDownTimer(1000L * 30, 1000L) {
            @Override
            public void onTick(long millisUntilFinished) {
                // your logic for tick
                Log.i("TEST", "onTick - " + Thread.currentThread() + ", id - " + Thread.currentThread().getId()+" "+millisUntilFinished);
            }

            @Override
            public void onFinish() {
                // your logic for finish

                Log.i("TEST", "onFinish" + Thread.currentThread() + ", id - " + Thread.currentThread().getId());
            }
        };
        countDownTimer.start();

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

在这里插入图片描述
回调执行在主线程,意味着可以在回调中直接处理UI,挺方便的。

2.2 工作线程中使用

在工作线程使用不能像在主线程一样简单使用,因为CountDownTimer是基于Handler的,主线程已经由安卓框架层启动了消息循环,可以直接使用。
那么在工作线程中怎样使用呢?可以借助HanderThread。在onLooperPrepared()中初始化并开启CountDownTimer:

    public static void test6() {
        new HandlerThread("TestThread") {
            protected void onLooperPrepared() {
                CountDownTimer countDownTimer = new CountDownTimer(1000L * 15, 1000L) {
                    @Override
                    public void onTick(long millisUntilFinished) {
                        // your logic for tick
                        Log.i("TEST", "onTick - " + Thread.currentThread() + ", id - " + Thread.currentThread().getId() + " " + millisUntilFinished);
                    }

                    @Override
                    public void onFinish() {
                        // your logic for finish
                        Log.i("TEST", "onFinish" + Thread.currentThread() + ", id - " + Thread.currentThread().getId());
                    }
                };
                countDownTimer.start();
            }
        }.start();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

在这里插入图片描述
这一次运行在HandlerThread封装的TestThread线程中。

三、使用注意

3.1 空指针

空指针:当一个Activity或Fragment被销毁时,如果CountDownTimer的onTick()方法还在继续执行,而UI控件已经为空(比如Activity或Fragment的生命周期已经结束,UI控件已经被销毁),那么在onTick()方法中对UI控件的操作就会导致空指针异常。这是因为UI控件已经不存在,无法进行正常的操作。

解决办法:一般要在activity或fragment销毁的时候调用cancle方法。

    @Override
    protected void onDestroy() {
        if (mCountDownTimer != null) {
            mCountDownTimer.cancel();
        }
        super.onDestroy();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

3.2 时间不是太准的问题

在CountDownTimer执行start后时,google源码里面减去了程序执行到这里的时候所消耗的时间

        public void handleMessage(Message msg) {

            synchronized (CountDownTimer.this) {
                if (mCancelled) {
                    return;
                }
                final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();

                if (millisLeft <= 0) {
                    onFinish();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

解决办法:
可以在构造方法里面稍微加一点时间就可以解决如60s

new CountDownTimer(60 * 1000+300, 1000)
  • 1

3.3 内存泄漏问题

如果外部类在CountDownTimer执行期间被销毁,但CountDownTimer仍然持有对外部类的引用,这就会导致外部类无法被正常回收,从而引发内存泄漏。

解决办法:使用弱引用持有UI控件

 WeakReference<TextView> tv;//控件软引用,防止内存泄漏
  • 1
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/808915
推荐阅读
相关标签
  

闽ICP备14008679号