Android中CountDownTimer类详解
一、概述
项目中经常用到倒计时的功能,比如说限时抢购,手机获取验证码等等。而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; } } }
到此这篇关于android中countdowntimer类详解的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: win11浏览器不能上网怎么办?win11无法联网修复教程
下一篇: 全球5G模组厂商型号价格对比
推荐阅读