Android CountDownTimer案例總結(jié)
一、概述
項(xiàng)目中經(jīng)常用到倒計(jì)時(shí)的功能,比如說(shuō)限時(shí)搶購(gòu),手機(jī)獲取驗(yàn)證碼等等。而google官方也幫我們封裝好了一個(gè)類(lèi):CountDownTimer,使我們的開(kāi)發(fā)更加方便;
二、API
CountDownTimer是一個(gè)抽象類(lèi),有兩個(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í)來(lái)看,點(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)閉銷(xiāo)毀的時(shí)候沒(méi)有調(diào)用cancle方法,它的onTick方法還是會(huì)繼續(xù)執(zhí)行,這個(gè)時(shí)候UI控件都為空,不注意判斷的話很容易空指針
2、時(shí)間不是太準(zhǔn)的問(wè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);
}
所以一開(kāi)始倒計(jì)時(shí)的時(shí)間是59,這里可以在構(gòu)造方法里面稍微加一點(diǎn)時(shí)間就可以解決如:
new CountDownTimer(60 * 1000+300, 1000)
3、內(nèi)存泄漏問(wèn)題
首先我們來(lá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)存泄漏問(wèn)題,當(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í)斐?所說(shuō)的空指針問(wèn)題,所以一般要在activity或fragment銷(xiāo)毀的時(shí)候調(diào)用cancle方法。
我自己把這個(gè)進(jìn)行了封裝,寫(xiě)成了一個(gè)工具類(lèi)以供參考:
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銷(xiāo)毀的時(shí)候調(diào)用,防止內(nèi)存泄漏
public void cancle() {
if (timer != null) {
timer.cancel();
timer = null;
}
}
}
到此這篇關(guān)于Android CountDownTimer案例總結(jié)的文章就介紹到這了,更多相關(guān)Android CountDownTimer內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android開(kāi)發(fā)實(shí)現(xiàn)的計(jì)時(shí)器功能示例
這篇文章主要介紹了Android開(kāi)發(fā)實(shí)現(xiàn)的計(jì)時(shí)器功能,涉及Android開(kāi)發(fā)中的計(jì)時(shí)器相關(guān)組件布局、調(diào)用、事件響應(yīng)等相關(guān)操作技巧,需要的朋友可以參考下2019-04-04
Android布局之LinearLayout自定義高亮背景的方法
這篇文章主要介紹了Android布局之LinearLayout自定義高亮背景的方法,實(shí)例分析了Android中LinearLayout布局參數(shù)設(shè)置技巧,需要的朋友可以參考下2016-01-01
Android 中HttpURLConnection與HttpClient使用的簡(jiǎn)單實(shí)例
這篇文章介紹了Android 中HttpURLConnection與HttpClient使用的簡(jiǎn)單實(shí)例,有需要的朋友可以參考一下2013-10-10
Android?RecyclerBarChart繪制使用教程
這篇文章主要為大家介紹了Android?RecyclerBarChart繪制使用教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
Android程序開(kāi)發(fā)之Listview下拉刷新上拉(滑動(dòng)分頁(yè))加載更多
這篇文章主要介紹了Android程序開(kāi)發(fā)之Listview下拉刷新上拉(滑動(dòng)分頁(yè))加載更多的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-07-07
Android內(nèi)容提供者ContentProvider用法實(shí)例分析
這篇文章主要介紹了Android內(nèi)容提供者ContentProvider用法,結(jié)合實(shí)例形式較為詳細(xì)的分析了內(nèi)容提供者ContentProvider獲取及解析數(shù)據(jù)的相關(guān)技巧,需要的朋友可以參考下2016-03-03
解決android 顯示內(nèi)容被底部導(dǎo)航欄遮擋的問(wèn)題
今天小編就為大家分享一篇解決android 顯示內(nèi)容被底部導(dǎo)航欄遮擋的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-07-07
Android編程記錄ListView標(biāo)記行狀態(tài)的方法
這篇文章主要介紹了Android編程記錄ListView標(biāo)記行狀態(tài)的方法,結(jié)合實(shí)例分析了ListView標(biāo)記的相關(guān)實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11

