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


猜你喜欢
- 利用ContentResolver访问者获取手机短信信息,在此记录一下,一遍以后查询。首先看一下结果,结果如下:activity_messa
- typora-copy-images-to: ./一键清除maven仓库中下载失败的jar包maven是一款非常优秀的项目管理工具,特别是其
- 首先,要学习Spring中的Bean的注入方式,就要先了解什么是依赖注入。依赖注入是指:让调用类对某一接口的实现类的实现类的依赖关系由第三方
- 比较适合新手。逻辑上仍然有点问题。可以用于学习java文件操作下载地址:http://yun.baidu.com/share/link?sh
- TreeWidget 目录树组件,该组件适用于创建和管理目录树结构,在开发中我们经常会把它当作一个升级版的ListView组件使用,因为Li
- 请求转发的三种方式SpringMVC请求转发区别于重定向,请求转发地址栏不会发生改变、只发送一次请求、能携带原有的参数,但只可以在同一个服务
- 在一个项目中,如果我们既用到了Struts2又用到了Servlet,项目运行时有可能无法正常访问Servlet,原因是在配置Struts的过
- 配置准备在build.gradle文件中添加如下依赖: compile "org.elasticsearc
- 代理模式代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基
- 这些bug可能够你喝一壶的。1、被断言(assert)包含的代码常发生在切换到release版本时,执行结果乖乖的,最终查找结果是asser
- 一般情况下是不可以用static修饰类的。如果一定要用static修饰类的话,通常static修饰的是匿名内部类。在一个类中创建另外一个类,
- 有想过hash["A1"] = DateTime.Now;这句是怎么实现的吗?我们来重温下学校时代就学过的哈希算法吧。我
- 双色球选号规则红球是1~33选6个,蓝球1~16选1个。它有17721088种排列组合,这个代码实现了如何将一组双色球号码 转换成第n个排列
- 本文将通过阅读spring源码,分析@Bean注解导入Bean的原理。从AnnotationConfigApplicationContext
- 一、前言先使用一个模板图片,在图片上添加图片或者文字都可以。二、依赖<dependency> <
- 我object != null要避免很多NullPointerException。有什么替代方法:if (someobject != nul
- 需要注意的一点是,feign好像是无法传递list集合类型的,但是你可以通过传递对象类型,然后在接收方再次将对象装在集合中达到集合传递的效果
- 我就废话不多说了,大家还是直接看代码吧~using UnityEngine;using System.Collections; public
- 下面我通过代码为大家分享下C#模拟鼠标,具体内容如下:想必有很多人在项目开发中可能遇见需要做模拟鼠标点击的小功能,很多人会在百度过后采用mo
- 前言本文主要给大家介绍了关于Java中Unsafe类的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧1.Unsaf