Android中CountDownTimer類詳解
一、概述
項(xiàng)目中經(jīng)常用到倒計(jì)時(shí)的功能,比如說限時(shí)搶購,手機(jī)獲取驗(yàn)證碼等等。而google官方也幫我們封裝好了一個(gè)類:CountDownTimer,使我們的開發(fā)更加方便;
二、API
CountDownTimer是一個(gè)抽象類,有兩個(gè)抽象方法,它的API很簡(jiǎn)單
public abstract void onTick(long millisUntilFinished);//這個(gè)是每次間隔指定時(shí)間的回調(diào),millisUntilFinished:剩余的時(shí)間,單位毫秒 public abstract void onFinish();//這個(gè)是倒計(jì)時(shí)結(jié)束的回調(diào)
使用的時(shí)候只需要
new CountDownTimer(long millisInFuture, long countDownInterval) //millisInFuture:倒計(jì)時(shí)的總時(shí)長(zhǎng) //countDownInterval:每次的間隔時(shí)間 單位都是毫秒
三、基本使用方法
我們以短信驗(yàn)證碼的倒計(jì)時(shí)來看,點(diǎn)擊獲取驗(yàn)證碼,倒計(jì)時(shí)60s不可點(diǎn)擊
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();
點(diǎn)擊按鈕,獲取驗(yàn)證碼成功之后就可以執(zhí)行以上操作,最后一定要start,不然不會(huì)執(zhí)行
四、使用注意
CountDownTimer使用很簡(jiǎn)單,但是坑很多,需要注意避免踩坑。
1、空指針:
如果在activity或者fragment關(guān)閉銷毀的時(shí)候沒有調(diào)用cancle方法,它的onTick方法還是會(huì)繼續(xù)執(zhí)行,這個(gè)時(shí)候UI控件都為空,不注意判斷的話很容易空指針
2、時(shí)間不是太準(zhǔn)的問題:
我們看CountDownTimer的源碼可以看到,在執(zhí)行onTick的方法時(shí),google源碼里面減去了程序執(zhí)行到這里的時(shí)候所消耗的時(shí)間,這里可以看出google代碼的嚴(yán)謹(jǐn)
final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime(); if (millisLeft <= 0) { onFinish(); } else if (millisLeft < mCountdownInterval) { // no tick, just delay until done sendMessageDelayed(obtainMessage(MSG), millisLeft); }
所以一開始倒計(jì)時(shí)的時(shí)間是59,這里可以在構(gòu)造方法里面稍微加一點(diǎn)時(shí)間就可以解決如:
new CountDownTimer(60 * 1000+300, 1000)
3、內(nèi)存泄漏問題
首先我們來看源碼,核心代碼如下
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,所以很容易造成內(nèi)存泄漏問題,當(dāng)Activity或者Fragment關(guān)閉而倒計(jì)時(shí)還未結(jié)束的時(shí)候,會(huì)在后臺(tái)一直執(zhí)行,而很多時(shí)候我們用倒計(jì)時(shí)會(huì)有更新UI的操作,而控件都持有activity的引用,長(zhǎng)期得不到釋放的話就會(huì)造成內(nèi)存泄漏,甚至?xí)斐?所說的空指針問題,所以一般要在activity或fragment銷毀的時(shí)候調(diào)用cancle方法。
我自己把這個(gè)進(jìn)行了封裝,寫成了一個(gè)工具類以供參考:
public class TimeUtils { private String color;//這里可以修改文字顏色 WeakReference<TextView> tvCodeWr;//控件軟引用,防止內(nèi)存泄漏 private CountDownTimer timer; public TimeUtils(TextView tvCode, String color) { super(); this.tvCodeWr = new WeakReference(tvCode); this.color = color; } //這是倒計(jì)時(shí)執(zhí)行方法 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(); } //這個(gè)方法可以在activity或者fragment銷毀的時(shí)候調(diào)用,防止內(nèi)存泄漏 public void cancle() { if (timer != null) { timer.cancel(); timer = null; } } }
到此這篇關(guān)于Android中CountDownTimer類詳解的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
如何利用Flutter實(shí)現(xiàn)酷狗流暢Tabbar效果
這篇文章主要給大家介紹了關(guān)于如何利用Flutter實(shí)現(xiàn)酷狗流暢Tabbar效果的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-02-02Android模擬實(shí)現(xiàn)華為系統(tǒng)升級(jí)進(jìn)度條
這篇文章主要介紹了如何通過Android模擬實(shí)現(xiàn)華為在系統(tǒng)升級(jí)時(shí)顯示的進(jìn)度條。文中的實(shí)現(xiàn)過程講解詳細(xì),感興趣的小伙伴可以動(dòng)手試一試2022-01-01android實(shí)現(xiàn)raw文件夾導(dǎo)入數(shù)據(jù)庫代碼
這篇文章主要介紹了android實(shí)現(xiàn)raw文件夾導(dǎo)入數(shù)據(jù)庫代碼,有需要的朋友可以參考一下2013-12-12Android仿IOS UIAlertView對(duì)話框
這篇文章主要為大家詳細(xì)介紹了Android仿IOS UIAlertView對(duì)話框,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06Android項(xiàng)目仿UC瀏覽器和360手機(jī)衛(wèi)士消息常駐欄(通知欄)
本篇文章主要介紹了Android項(xiàng)目仿UC瀏覽器和360手機(jī)衛(wèi)士消息常駐欄(通知欄),可以仿照360的通知欄,有興趣的可以了解一下。2016-11-11