把倒計時做到極致

版權(quán)聲明:

本賬號發(fā)布文章均來自公眾號诫睬,承香墨影(cxmyDev)帕涌,版權(quán)歸承香墨影所有。

未經(jīng)允許亲澡,不得轉(zhuǎn)載纫版。

一、前言

倒計時這種癞己,每秒更新 UI 的需求梭伐,應(yīng)該算是比較常見的了。最常見的場景练慕,就是驗證碼發(fā)送超時重試的邏輯技掏,這個邏輯中需要一個倒計時的邏輯去每秒修改 UI ,讓倒計時做到用戶可感知劲阎。

那么倒計時的邏輯鸠真,需要如何做到極致?

一個倒計時锡垄,最少要有兩個要求:準(zhǔn)祭隔、穩(wěn)。

準(zhǔn)就是說,一個 2 分鐘的倒計時屯仗,就應(yīng)該執(zhí)行兩分鐘搔谴,穩(wěn)的意思就是說,每次同步 UI 的更新慌核,都是差不多間隔 1s申尼。

二垫桂、實現(xiàn)思路

1诬滩、每次延遲 1s 通知 UI 更新

倒計時說白了就是一個間隔固定時間去做一件固定任務(wù),這樣的功能疼鸟,最簡單的就是使用 Handler.postDelayed() 去間隔執(zhí)行。

那么我們寫一個 CountdownUtils 的類浩淘,先看看它的結(jié)構(gòu)吴攒。


可以看到洼怔,它是基于一個 Handler 來做延遲的。這個邏輯非常的簡單极谊,直接上代碼了安岂。


使用起來也非常的簡單,傳遞進去 2 分鐘的時長蜕依。

new CountdownUtils(120).start()

看看 Log 輸出的結(jié)果,

從 Log 上看友瘤,確實是完成了一個倒計時的功能檐束,一秒一秒一直到 0 ,但是這里為了觀察準(zhǔn)不準(zhǔn)盟戏,對倒計時執(zhí)行的完整時間做了一個間隔記錄甥桂,看到問題了嗎?一個 120s 的倒計時蝇摸,卻執(zhí)行了 124s 左右办陷。

這個問題實際上是因為 Handler.postDelayed() 的間隔時長,并不是準(zhǔn)確的間隔指定的時長啡专,具體什么時候執(zhí)行制圈,實際上是看線程的調(diào)度的。這種總時長差異的問題病附,換了 Timer 什么的去實現(xiàn)也是無法解決的亥鬓。

這個問題,在一些驗證碼倒計時的場景下覆积,沒有參照事件點熟呛,每個倒計時,誤差幾十毫秒庵朝,基本上是用戶無感知的。但是有一些情況下椎瘟,例如視頻播放的倒計時肺蔚,這種有參照的情況下,幾分鐘的倒計時宣羊,誤差幾秒鐘,就是非常明顯的 Bug 了之宿。

這就是不穩(wěn)苛坚,那么,如何把倒計時做的穩(wěn)呢?

2柠掂、 使用 CountDownTimer

實現(xiàn)一個倒計時依沮, Android 其實是提供了對應(yīng)的支持類的,那就是 CounDownTimer 宋渔,它處于 android.os 包下的辜限,完全可以實現(xiàn)一個倒計時的邏輯。

我們先看看它是如何使用的氧急。


CountDownTimer 的使用非常的簡單毫深,在 onTick() 中監(jiān)聽倒計時的變化哑蔫,結(jié)束的時候會去調(diào)用 onFinish()弧呐。

繼續(xù)運行一下看看 Log 的輸出情況嵌纲。


這個總時長疹瘦,誤差已經(jīng)是毫秒級的了,看樣子比我們自己實現(xiàn)的好很多言沐。

再仔細(xì)看看,onTick() 方法回調(diào)的參數(shù)汹押,是一個 毫秒 為單位的數(shù)值起便,而這個數(shù)值榆综,其實是有誤差的,但是這個其實也不影響鼻疮,只需要對其進行四舍五入的運算判沟,就可以得到正確的倒計時秒數(shù)。

例如:2830 就是 3s挪哄,1828 就是 2s。

但是再仔細(xì)看看迹炼,就能發(fā)現(xiàn)問題,如果使用這種方式來處理倒計時的話拿霉,你會發(fā)現(xiàn)咱扣,拿不到 1s 的狀態(tài)闹伪,會直接 3s - 2s - finish壮池,這個問題杀怠,從 Log 上也可以反應(yīng)出來。

這就很尷尬了橙依,有沒有參照物硕旗,都是一個 Bug,只能先看看 CountDownTimer 的源碼了创译,它是如何保證總時長的準(zhǔn)確的墙基。


從 CountDownTimer 的結(jié)構(gòu)可以看出残制,它實際上也是使用 mHandler 來做的延遲,繼續(xù)看最重要的 Handler 的實現(xiàn)代碼颗祝。


在 handleMessage() 中纺蛆,用到了一個 SystemClock.elapsedRealtime() 规揪,它實際上獲取到的是一個 系統(tǒng) 啟動之后猛铅,到現(xiàn)在的一個絕對時間,包含系統(tǒng)休眠的間隔堕伪。


但是栗菜,它并不是關(guān)鍵,關(guān)鍵在于富俄,CountDownTimer 會使用這個時間,每次計算出一個相對 1s 間隔的差值幕袱,也就是說悠瞬,每次都去糾正這個誤差值,來保證最終的總時長誤差是毫秒級(其實就是最后一次 postDelayed() 的誤差)望迎。

既然找到了 CountDownTimer 保證時間準(zhǔn)確行的關(guān)鍵點狂打,那么我們可以改寫第一個 Demo 的代碼,來解決沒有 1s 狀態(tài)的問題对省。

3晾捏、 動態(tài)計算 delay 值

沒什么好說的,就是計算此次間隔耗時劳秋,然后比 1s 多出來的毫秒值胖齐,從下一個 1s 中減去呀伙,來糾正間隔時長。


既然實現(xiàn)了之后箫锤,我們再看看輸出的 Log雨女。


可以看到氛堕,interval 每一次都在動態(tài)的調(diào)整,每一秒的狀態(tài)都會更新出去括儒,并且總時長也保證誤差在毫秒級的,基本上完美解決了倒計時的問題了七冲。

三规婆、小結(jié)

一個倒計時,簡簡單單使用 Handler.postDelayed() 也是無法保證準(zhǔn)和穩(wěn)的掘鄙。細(xì)節(jié)決定成敗嗡髓,一個倒計時也是可以做到極致的。

公眾號二維碼.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市长捧,隨后出現(xiàn)的幾起案子串结,更是在濱河造成了極大的恐慌,老刑警劉巖卧蜓,帶你破解...
    沈念sama閱讀 222,627評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件把敞,死亡現(xiàn)場離奇詭異,居然都是意外死亡其爵,警方通過查閱死者的電腦和手機伸蚯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評論 3 399
  • 文/潘曉璐 我一進店門剂邮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來横侦,“玉大人绰姻,你說我怎么就攤上這事狂芋『┰裕” “怎么了?”我有些...
    開封第一講書人閱讀 169,346評論 0 362
  • 文/不壞的土叔 我叫張陵屡萤,是天一觀的道長掸宛。 經(jīng)常有香客問我唧瘾,道長,這世上最難降的妖魔是什么饰序? 我笑而不...
    開封第一講書人閱讀 60,097評論 1 300
  • 正文 為了忘掉前任菌羽,我火速辦了婚禮注祖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘是晨。我一直安慰自己,他們只是感情好蚊逢,可當(dāng)我...
    茶點故事閱讀 69,100評論 6 398
  • 文/花漫 我一把揭開白布烙荷。 她就那樣靜靜地躺著檬寂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪昼伴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,696評論 1 312
  • 那天价涝,我揣著相機與錄音飒泻,去河邊找鬼吏廉。 笑死,一個胖子當(dāng)著我的面吹牛史辙,可吹牛的內(nèi)容都是我干的佩伤。 我是一名探鬼主播,決...
    沈念sama閱讀 41,165評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼耙蔑,長吁一口氣:“原來是場噩夢啊……” “哼孤荣!你這毒婦竟也來了盐股?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,108評論 0 277
  • 序言:老撾萬榮一對情侶失蹤牲尺,失蹤者是張志新(化名)和其女友劉穎幌蚊,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蜒简,經(jīng)...
    沈念sama閱讀 46,646評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡臭蚁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,709評論 3 342
  • 正文 我和宋清朗相戀三年垮兑,在試婚紗的時候發(fā)現(xiàn)自己被綠了漱挎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,861評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡私爷,死狀恐怖膊夹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情工秩,我是刑警寧澤进统,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布螟碎,位于F島的核電站,受9級特大地震影響俭缓,放射性物質(zhì)發(fā)生泄漏酥郭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,196評論 3 336
  • 文/蒙蒙 一季春、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧消返,春花似錦载弄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至倡勇,卻和暖如春逞刷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評論 1 274
  • 我被黑心中介騙來泰國打工夸浅, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留仑最,地道東北人。 一個月前我還...
    沈念sama閱讀 49,287評論 3 379
  • 正文 我出身青樓警医,卻偏偏與公主長得像,于是被迫代替她去往敵國和親坯钦。 傳聞我的和親對象是個殘疾皇子预皇,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,860評論 2 361

推薦閱讀更多精彩內(nèi)容