Android CountDownTimer案例总结

作者:weixin_42564441 时间:2023-12-21 05:40:36 

一、概述

项目中经常用到倒计时的功能,比如说限时抢购,手机获取验证码等等。而google官方也帮我们封装好了一个类:CountDownTimer,使我们的开发更加方便;

二、API

CountDownTimer是一个抽象类,有两个抽象方法,它的API很简单


public abstract void onTick(long millisUntilFinished);//这个是每次间隔指定时间的回调,millisUntilFinished:剩余的时间,单位毫秒
public abstract void onFinish();//这个是倒计时结束的回调

使用的时候只需要


new CountDownTimer(long millisInFuture, long countDownInterval)

//millisInFuture:倒计时的总时长

//countDownInterval:每次的间隔时间  单位都是毫秒

三、基本使用方法

我们以短信验证码的倒计时来看,点击获取验证码,倒计时60s不可点击


new CountDownTimer(60 * 1000, 1000) {
   @Override
   public void onFinish() {
       if (tvCode != null) {
           tvCode.setText("重新获取");
           tvCodeWr.setTextColor(Color.parseColor("#E94715"));
           tvCode.setClickable(true);
           tvCode.setEnabled(true);
       }

cancel();
   }

@Override
   public void onTick(long millisUntilFinished) {
       if (tvCode != null) {
           tvCode.setClickable(false);
           tvCode.setEnabled(false);
           tvCode.setText(millisUntilFinished / 1000 + "s");
           tvCode.setTextColor(Color.parseColor("#999999"));
       }
   }
}.start();

点击按钮,获取验证码成功之后就可以执行以上操作,最后一定要start,不然不会执行

四、使用注意

CountDownTimer使用很简单,但是坑很多,需要注意避免踩坑。

1、空指针:如果在activity或者fragment关闭销毁的时候没有调用cancle方法,它的onTick方法还是会继续执行,这个时候UI控件都为空,不注意判断的话很容易空指针

2、时间不是太准的问题:

    我们看CountDownTimer的源码可以看到,在执行onTick的方法时,google源码里面减去了程序执行到这里的时候所消耗的时间,这里可以看出google代码的严谨


final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();

if (millisLeft <= 0) {
   onFinish();
} else if (millisLeft < mCountdownInterval) {
   // no tick, just delay until done
   sendMessageDelayed(obtainMessage(MSG), millisLeft);
}

所以一开始倒计时的时间是59,这里可以在构造方法里面稍微加一点时间就可以解决如:


new CountDownTimer(60 * 1000+300, 1000)

3、内存泄漏问题

    首先我们来看源码,核心代码如下


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) {
               // no tick, just delay until done
               sendMessageDelayed(obtainMessage(MSG), millisLeft);
           } else {
               long lastTickStart = SystemClock.elapsedRealtime();
               onTick(millisLeft);

// take into account user's onTick taking time to execute
               long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();

// 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,所以很容易造成内存泄漏问题,当Activity或者Fragment关闭而倒计时还未结束的时候,会在后台一直执行,而很多时候我们用倒计时会有更新UI的操作,而控件都持有activity的引用,长期得不到释放的话就会造成内存泄漏,甚至会造成1所说的空指针问题,所以一般要在activity或fragment销毁的时候调用cancle方法。

我自己把这个进行了封装,写成了一个工具类以供参考:


public class TimeUtils {
   private String color;//这里可以修改文字颜色
   WeakReference<TextView> tvCodeWr;//控件软引用,防止内存泄漏
   private CountDownTimer timer;

public TimeUtils(TextView tvCode, String color) {
       super();
       this.tvCodeWr = new WeakReference(tvCode);
       this.color = color;
   }
//这是倒计时执行方法
   public void RunTimer() {
       timer = new CountDownTimer(60 * 1000 - 1, 1000) {
           @Override
           public void onFinish() {
               if (tvCodeWr.get() != null) {
                   tvCodeWr.get().setText("重新获取");
                   tvCodeWr.get().setTextColor(Color.parseColor(color));
                   tvCodeWr.get().setClickable(true);
                   tvCodeWr.get().setEnabled(true);
               }

cancel();
           }

@Override
           public void onTick(long millisUntilFinished) {
               if (tvCodeWr.get() != null) {
                   tvCodeWr.get().setClickable(false);
                   tvCodeWr.get().setEnabled(false);
                   tvCodeWr.get().setText(millisUntilFinished / 1000 + "s");
                   tvCodeWr.get().setTextColor(Color.parseColor("#999999"));
               }
           }
       }.start();
   }
//这个方法可以在activity或者fragment销毁的时候调用,防止内存泄漏
   public void cancle() {
       if (timer != null) {
           timer.cancel();
           timer = null;
       }
   }
}

来源:https://blog.csdn.net/weixin_42564441/article/details/80967482

标签:Android,CountDownTimer
0
投稿

猜你喜欢

  • C#中数组初始化与数组元素复制的方法

    2023-05-14 15:45:06
  • C#中Params的用法

    2023-06-03 22:23:27
  • 深入理解堆排序及其分析

    2022-05-09 00:16:09
  • 浅谈Java中ThreadLocal内存泄露的原因及处理方式

    2021-06-12 21:08:37
  • 基于Spring Boot保护Web应用程序

    2022-11-15 19:14:48
  • springboot搭建访客管理系统的实现示例

    2023-09-02 13:10:41
  • Android编程实现仿QQ发表说说,上传照片及弹出框效果【附demo源码下载】

    2022-10-02 11:59:43
  • spring中bean id相同引发故障的分析与解决

    2023-08-05 11:30:41
  • Android滑动冲突的完美解决方案

    2021-08-12 16:41:34
  • C++ 风靡一时的连连看游戏的实现流程详解

    2022-10-08 13:39:12
  • C#切换鼠标左右键习惯无需控制面板中修改

    2021-08-06 04:44:44
  • javafx实现五子棋游戏

    2022-02-01 07:00:01
  • java实现网站微信扫码支付

    2023-06-18 18:58:19
  • springcloud gateway如何实现路由和负载均衡

    2023-01-09 07:13:35
  • Java中instanceof关键字的用法总结

    2022-12-11 15:52:27
  • java.lang.Runtime.exec的左膀右臂:流输入和流读取详解

    2023-08-06 04:59:03
  • Java实现分布式系统限流

    2022-05-31 22:38:05
  • C# 给PPT中的图表添加趋势线的方法

    2022-02-27 10:18:40
  • Android viewpager 3D画廊的实现方法

    2021-05-28 21:19:27
  • C# Winform实现捕获窗体最小化、最大化、关闭按钮事件的方法

    2021-10-18 08:01:29
  • asp之家 软件编程 m.aspxhome.com