CountDownTimer使用——android倒計時

??????? 相信大家在項目里面不少會用到倒計時操作吧,倒計時功能在我們業務開發中使用概率非常高,例如用戶操作姿勢錯誤,我們給一個提示,提示是帶有倒計時的對話框,當然你會問為什么不直接用Toast呢?

??????? 確實,我們可以直接用土司,但是往往這不是產品想要的,他們覺得沒有交互,體驗很差,再例如我們用戶完成某個任務也可以通過這種倒計時框給用戶提醒,倒計時操作再android開發需求很廣泛,這里就不多說。

?????? 在andriod中倒計時的實現也有很多種,你可以通過最常用的Handler+Thread方式實現,也可以通過Timer方式實現,當然也可以通過本章要介紹的Google官方推薦的CountDownTimer來實現,當然解決問題的方式又很多,不僅僅就這幾種方法,這幾種只是個眾多方法中的代表,像Handler實現倒計時還有很多變種,例如很Message搭配方式,跟Runnable結合使用方式等等,總之,歸根結底都是在子線程進行耗時操作,在UI線程進行更新。


那么現在我們分別介紹這幾種不同的方式:

1)通過Handler+Thread/Runnable方式

先上碼再說:

handler+Thread

正如大家所見我們在主線程中創建一個Handler,通過handler機制來更新我們的UI,這里更新UI是指我們展示給大家看的倒計時,這里我只介紹倒計時的邏輯和實現,具體應用在什么場景大家自己發揮吧,你可以展示在一個TextView上,也可以彈出一個對話框當作提示,這里我們對倒計時的載體忽略,大家關心倒計時的邏輯并根據情況移植到自己的案例中。

我們在主線程中(即ui線程)創建一個handler,這里我們用到handler消息機制,不明白的可以去看這篇文章www.lxweimin.com/p/138363a97da8

在handler中對控件更新內容,這里指秒數,再自減向下循環,然后通過handler將消息發送出去,是通過handler.sendEmptyMessageDelayed(0,1),第一個參數是延遲時間,第二個參數是時間間隔,當second小于0的時候,這時候倒計時完畢,我們就必須取消發送,通過removeCallbacksAndMessages()方法,不然handler會內存泄漏導致程序崩潰,就這樣完了???? 似乎我們還確定什么,對,一開始我們就在handler中處理MessageQueue中的消息,但是第一條消息來自哪兒? 好像沒找到,沒錯,這里我省略掉了我們第一條消息這個引子,再次上圖:

創建線程開啟循環

這里的show方法大家可以不用關心,因為我這里倒計時放在對話彈框里面,屬于對話框的邏輯,大家可以調用new Thread(new MyThread()).start()直接開啟我們的倒計時,這就是handler的實現倒計時,熟悉Handler機制的同學理解起來應該沒問題。



2)直接通過Handler方式

這種方式跟上一種區別在于handler是在oncreate()中創建的(initView()在onCreate()方法中),activity創建的時候會調用生命周期函數完成其整個生命過程,在onCreate中會創建hanlder,然后通過obtainMessage()創建Message,最后通過sendEmptyMessage()將消息發送出去,這里message我們只是創建但是空的,因為我們不需要攜帶消息到UI線程,所以我們向MessageQueue發送一條新消息,然后handler進入循環狀態,線程內部Looper開始輪詢不斷從MwssageQueue中取出消息分發給handler處理,知道所有消息處理完,handler不再發送消息為止,這個過程業務層面的實現也就是handleMessage()中的邏輯,我們在handler初始化的時候可以設定一個倒計時時長——mLimitTime,在oncreate()中就發送一條空消息讓handler循環起來,每一次處理消息時候對時長mLimitTime進行判斷,在對應的控件上更新當前時長,不要忘了mLimitTime--,不斷循環直到我們時長等于0也就是else流程,這里我回調對話框dismiss()方法,在這個方法里面我們需要removeCallbacksAndMessages()取消我們的handler機制,防止出現內存泄漏,跟方式1邏輯上沒有太大的差別,主要熟悉handler機制。

不過這種方式我用的是Kotlin實現的,如果第一次接觸Kotlin的可能看起來不是很舒服,但是對于會Java的人來說應該不是太大問題,你也可以根據這個邏輯用java實現這個倒計時。


3)Timer倒計時方式

?????? 例外使用Timer和TimerTask也是很簡單,用法很固定,所以大家直接根據模板調用就行,首先我們在類初始化的時候創建好Timer和TimerTask,這個和Handler用法很相似,task的內部我們是通過runOnUiThread()方式在ui線程更狀態,循環邏輯也是差不多,當我們倒數計時長recLen等于0的時候我們就cancel()取消Timer操作,這和handler的removecallbackandMessage()差不多,后面的Intent大家直接可以忽略,這個是針對業務的邏輯,然后準備工作都完成后,我們在onFinishCreateView()中通過schedule(task,0,1000)開啟這個task,這個和使用handler機制中的sendEmptyMessage()作用是一樣的,這里的onFinishCreateView()方法也是業務需求方法,大家可以把task.schedule()放到onCreate()或者onResume()啟動方法中,開啟任務并進行循環,直到條件不合理跳出循環,期間每次循環都更新控件內容。

是不是很簡單?。。。?/p>

創建Timer
創建任務


4)CountDownTimer Google墻裂推薦方式:

那我們來看一看google到底是如何來封裝這一款倒計時的

構造方法:

CountDownTimer構造

millisInFuture:倒計時時長,

countDownInterval:倒計時時間隔


啟動程序段

首先會對millisInFuture合理判斷,倒計時不合理就直接finish掉,mStopTimeInFuture=SystemClock.elapsedRealtime()+mMillisInFuture獲取倒計時終止完成時間,是什么意思呢? 先拿到們系統當前時長,然后再加上我們倒計時時長,相當于再代碼中對終止時間做了一個標記mStopTimeInFuture,接著看,是不是出現很熟悉的代碼——sendMessage(),原來CountDownTime內部已經為我們封裝好了handler機制,怪不得Google非常推薦得方式,避免開發者開發過程中姿勢使用不對導致內存泄漏引發程序崩潰,接著繼續看源碼


handler消息處理

這里就是處理消息的邏輯,首先google為了程序的健壯性和一致性為當前倒計時任務進行枷鎖,大家看這段代碼:final longmillisLeft=mStopTimeInFuture-SystemClock.elapsedRealtime();? 每次從消息隊列中取出消息都會計算剩下時長,同樣對剩下時長進行合理判斷,有一點需要注意,onTick(millisLeft)這是個啥東西,好像是個回調方法,確實google為我們抽象了兩個比較常用的回調方法,當我們沒執行一個時間間隔后,就會調用這個回調方法更新我們控件狀態等操作,接著看:


向消息隊列中發送消息


沒錯,內部不斷循環發送消息,handler的用法主要就是這些,無非是google替我們封裝好了邏輯,同理直到millisLeft等于0回調onFinish()方法

回調方法


上面我們將源碼簡單過了一下,下面我們繼續貼代碼,看看該怎么用:

定義一個TimerCount繼承CountDownTimer


實例化倒計時類并開啟任務

onFinish()和onTick()方法你可以自由發揮,根據需求來執行邏輯,

其實有個更簡單做法,直接new出一個CountDownTimer()并start這個倒計時就ok了 ,然后在回調里面進行UI更新操作,不用在定義一個TimeCount,之所以這樣寫因為擴展性好。

到此,我們介紹的幾種倒計時基本結束了,說來說去無非就是handler的用法以及對其進行的封裝,還不是很了解handler的寶寶去看一下handler的文章,暫時就先到這了,祝大家周末愉快喲?。。?/p>

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,659評論 25 708
  • 概述 Android應用啟動時就會為應用創建一個主線程,由于UI操作都是在主線程中進行的,所以主線程也稱為 UI ...
    小蕓論閱讀 529評論 0 0
  • Android的消息傳遞機制是另一種形式的“事件處理”,這種機制主要是為了解決Android應用的多線程問題——A...
    trampcr閱讀 8,781評論 2 20
  • 一個成功的男人,25歲的時候是一個好兒子,35歲的時候是一個好丈夫,45歲的時候是一個好爸爸! ——張雪峰
    哼哼傻豬豬閱讀 200評論 0 0
  • 曲江池上雨,老槐樹下人。 隱隱霧中樓,漫漫雨侵心。
    PoYee閱讀 204評論 0 1