CountDownTimer_countdowntimer暂停

CountDownTimer_countdowntimer暂停一,概述在项目开发中经常会用到倒计时这个功能,而Android也帮我们封装好了一个类CountDownTimer,给我们的开发带来了很大的方便;二,APICountDownTimer(longmillisInFuture,longcountDownInterval)参数1,设置倒计时的总时间(毫秒)参数2,设置每次减去多少毫秒123三,基本用法以App中获短信取验证码为例:pr…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

一,概述

在项目开发中经常会用到倒计时这个功能,而Android也帮我们封装好了一个类CountDownTimer,给我们的开发带来了很大的方便;

二,API

CountDownTimer (long millisInFuture, long countDownInterval)
参数1,设置倒计时的总时间(毫秒)
参数2,设置每次减去多少毫秒
  • 1
  • 2
  • 3

三,基本用法

以App中获短信取验证码为例:

    private Button btn;
    private TextView vertifyView;  

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initView();
    }

    private void initView(){
        vertifyView =(TextView) findViewById(R.id.vertifyView);
        btn =(Button) findViewById(R.id.button);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //1,请求后台...

                //2,触发定时器刷新UI(启动代码最好放在请求后台回调成功之后)
                timer.start();
            }
        });
    }

    private CountDownTimer timer = new CountDownTimer(10000, 1000) {  

        @Override  
        public void onTick(long millisUntilFinished) {  
            vertifyView.setText((millisUntilFinished / 1000) + "秒后可重发");  
        }  

        @Override  
        public void onFinish() {  
            vertifyView.setEnabled(true);  
            vertifyView.setText("获取验证码");  
        }  
    };  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

ok~这样一个基本的CountDownTimer案例就完成了

四,存在的问题

CountDownTimer如果使用不当,常常会报空指针异常,甚至造成严重的内存泄漏 
5.0源码:

public abstract class CountDownTimer { 
   

    /** * Millis since epoch when alarm should stop. */
    private final long mMillisInFuture;

    /** * The interval in millis that the user receives callbacks */
    private final long mCountdownInterval;

    private long mStopTimeInFuture;

    /** * boolean representing if the timer was cancelled */
    private boolean mCancelled = false;

    /** * @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. */
    public CountDownTimer(long millisInFuture, long countDownInterval) {
        mMillisInFuture = millisInFuture;
        mCountdownInterval = countDownInterval;
    }

    /** * Cancel the countdown. */
    public synchronized final void cancel() {
        mCancelled = true;
        mHandler.removeMessages(MSG);
    }

    /** * Start the countdown. */
    public synchronized final CountDownTimer start() {
        mCancelled = false;
        if (mMillisInFuture <= 0) {
            onFinish();
            return this;
        }
        mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
        mHandler.sendMessage(mHandler.obtainMessage(MSG));
        return this;
    }


    /** * 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();


    private static final int MSG = 1;


    // 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 if (millisLeft < mCountdownInterval) {
                    // 剩余时间小于一次时间间隔的时候,不再通知,只是延迟一下
                    sendMessageDelayed(obtainMessage(MSG), millisLeft);
                } else {
                    long lastTickStart = SystemClock.elapsedRealtime();
                    onTick(millisLeft);

                     // 处理用户onTick执行的时间
                    long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();

                     // 特殊情况:用户的onTick方法花费的时间比interval长,那么直接跳转到下一次interval
                    while (delay < 0) delay += mCountdownInterval;

                    sendMessageDelayed(obtainMessage(MSG), delay);
                }
            }
        }
    };
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103

从源码中我们可以看出,CountDownTimer的内部实现是采用Handler机制,通过sendMessageDelayed延迟发送一条message到主线程的looper中,然后在自身中收到之后判断剩余时间,并发出相关回调,然后再次发出message的方式。

这样的方式其实是有一定弊端的,那就是如果在Activity或者Fragment被回收时并未调用CountDownTimer的cancel()方法结束自己,这个时候CountDownTimer的Handler方法中如果判断到当前的时间未走完,那么会继续调用

sendMessageDelayed(obtainMessage(MSG), delay);
  • 1

触发

onTick(millisLeft);
  • 1

当回调了Activity或者fragment中CountDownTimer的onTick方法时,Activity或者Fragment已经被系统回收,从而里面的变量被设置为Null,再调用

vertifyView.setText((millisUntilFinished / 1000) + "秒后可重发"); 
  • 1

vertifyView为空,也就空指针了~ 
同时,CountDownTimer中的Handler方法还在继续执行,这一块空间始终无法被系统回收也就造成了内存泄漏问题。

五,总结

1,在CountDownTimer的onTick方法中记得判空

activity中
    if(!activity.isFinishing()){
        //doing something...
    }

fragment中
    if(getActivity()!=null){
       //doing something...
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2,在配合DialogFragment使用时,如果在onFinish()方法调用了 dismiss()方法让弹框消失,记得 判断getFragmentManager是否为空

    @Override
    public void onFinish() {
        if(getFragmentManager()!=null){
            dismiss();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

3,在使用CountDownTimer时,在宿主Activity或fragment生命周期结束的时候,记得调用timer.cancle()方法

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

遇到问题还是尽量先从控件的源码中寻找答案~相信源码是最好的老师O(∩_∩)O哈哈~

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/192098.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • idea正版在线激活码破解方法「建议收藏」

    idea正版在线激活码破解方法,https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月14日
    141
  • css动画和js动画的优缺点_彼得兔第三季动画片

    css动画和js动画的优缺点_彼得兔第三季动画片大家好,我是小丞同学,一名准大二的前端爱好者这篇文章将欢快的带你了解一下CSS和JS动画的差别愿你忠于自己,热爱生活引言讲到动画,当然是非常有意思的啦,你可以往上滑一下,看看上面的封面图,是不是相当的炫酷,以为我是代码写出来的吗?那当然不可能啊,我这么摸鱼,怎么会为了个封面图上号呢废话不多说,其实上面的动图用代码实现也不会很困难,这个图是用canva做出来的。本文主要讲以下这些内容浏览器渲染流程回流和重绘CSS动画JS动画两者对比

    2022年10月15日
    0
  • c语言 按字节异或,C语言位数算,按位异或.只知道按位异或原理 不知道这题怎么做…

    c语言 按字节异或,C语言位数算,按位异或.只知道按位异或原理 不知道这题怎么做…从键盘读入两个整数,对它们进行按位异或操作,把操作结果按二进制位放在字符数组str中,最后输出该字符串。提示:第2个空建议使用条件表达式(?表达式)实现!程序的运行效果应类似地如图1和图2所示,图1中的1270和图2中的123456是从键盘输入的内容。Pleaseinputnum1andnum2:1270127^0=0000000000000000000000000111…

    2022年6月5日
    26
  • 树后台数据存储(採用webmethod)[通俗易懂]

    树后台数据存储(採用webmethod)

    2022年1月24日
    39
  • 京东云服务器免费6月_福利服务器

    京东云服务器免费6月_福利服务器记得是在2010年,那个时候我刚刚开始接触Android不久,Google也还没有离开中国。当时我在上大三,Google举办了一场Android应用开发中国大学生挑战赛,跃跃欲试的我就和同学组队一起参加了。当时我们开发的项目叫做酷欧短信(没错,你们所熟悉的酷欧天气其实就是从这个名字演变过来的),是一款功能比较丰富的短信收发软件。我个人对这个项目当时是非常有信心的,不过最终结果下来却只获得了

    2022年10月14日
    0
  • matlab中fprintf函数的用法举例_matlabfopen函数的用法

    matlab中fprintf函数的用法举例_matlabfopen函数的用法fprintf函数在matlab具体应用clcclearage=18;name=’小飞’;fprintf(‘%s的年龄是%d。\n’,name,age)说明:\n表示换行示例clcclearsymsabna=5;b=4;n=30;D(1)=a+b;D(2)=(a+b).^2-a*b;fori=3:nD(i)=D(i-1)*(a+b)-a*b*D(i-2);fprint.

    2022年10月19日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号