????小菜在學(xué)習(xí) Flutter 過程中宁赤,可能會(huì)遇到倒計(jì)時(shí)等需求,此時(shí)需要用到 Timer 計(jì)時(shí)器,小菜簡單嘗試一下偎痛;
Timer
????Timer 作為一個(gè)抽象類,提供了兩種工廠方法進(jìn)行調(diào)用独郎;可以作為一次或者重復(fù)觸發(fā)的倒計(jì)時(shí)計(jì)時(shí)器踩麦;
案例嘗試
1. Timer()
factory Timer(Duration duration, void Function() callback) {
if (Zone.current == Zone.root) {
return Zone.current.createTimer(duration, callback);
}
return Zone.current.createTimer(duration, Zone.current.bindCallbackGuarded(callback));
}
????Timer 允許指定延遲時(shí)間之后執(zhí)行枚赡,通過設(shè)置 Timeout 來指定延遲時(shí)間,之后通過 callback 回調(diào)對(duì)執(zhí)行結(jié)果進(jìn)行監(jiān)聽處理谓谦;
Timer(Duration(seconds: 3), () {
print("_timer01() -> Timer(Duration(seconds: 3) printed after 3 seconds");
Toast.show('Timer(Duration(seconds: 3) printed after 3 seconds !', context,
duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);
});
2. Timer.periodic()
factory Timer.periodic(Duration duration, void callback(Timer timer)) {
if (Zone.current == Zone.root) {
return Zone.current.createPeriodicTimer(duration, callback);
}
var boundCallback = Zone.current.bindUnaryCallbackGuarded<Timer>(callback);
return Zone.current.createPeriodicTimer(duration, boundCallback);
}
????簡單了解 Timer.periodic() 命名構(gòu)造方法可得贫橙,該命名構(gòu)造方法通過定時(shí)綁定回調(diào)進(jìn)行再次 Timer 倒計(jì)時(shí)處理;
????Timer.periodic() 可以重復(fù)性反粥、周期性的進(jìn)行倒計(jì)時(shí)卢肃,若不進(jìn)行手動(dòng)調(diào)用,則會(huì)一直關(guān)閉才顿,即便頁面關(guān)閉也會(huì)繼續(xù)調(diào)用莫湘;
????其中 Timer.tick 為調(diào)用次數(shù),Timer.isActive 代表當(dāng)前 Timer 是否處于活躍狀態(tài)娜膘;
Timer.periodic(Duration(seconds: 2), (timer) {
print('_timer02() -> Timer.periodic() -> Timer.tick -> ${timer.tick} -> Timer.isActive -> ${timer.isActive}');
});
3. Timer.run()
static void run(void Function() callback) {
new Timer(Duration.zero, callback);
}
????Timer 的執(zhí)行為異步操作逊脯,Flutter 提供了便利的 Timer.run() 命名構(gòu)造函數(shù)可以方便盡快執(zhí)行,可以簡單理解為倒計(jì)時(shí)為 0竣贪;
????小菜嘗試了如下操作順序军洼,首先執(zhí)行同步的 A -> B -> C,之后才會(huì)是異步的 run() 和 Duration.zero演怎;
print('_timer03() -> A');
Timer.run(() {
print('_timer03() -> Timer.run()');
});
print('_timer03() -> B');
Timer(Duration.zero, () {
print('_timer03() -> Duration.zero');
});
print('_timer03() -> C');
4. cancel()
????Timer() 計(jì)時(shí)器可以通過 cancel() 來取消匕争,尤其是在進(jìn)行周期性的 Timer.periodic() 調(diào)用時(shí),需要在合適的時(shí)機(jī)及時(shí)取消爷耀;小菜嘗試在 Timer() 回調(diào)內(nèi)取消和方法外回調(diào)兩種方式甘桑;
4.1 Timer() 回調(diào)內(nèi)取消
Timer.periodic(Duration(seconds: 2), (timer) {
if (timer.tick == 3) {
timer.cancel();
}
print('_timer04() -> Timer.periodic() -> Timer.tick -> ${timer.tick} -> Timer.isActive -> ${timer.isActive}');
});
4.2 方法外取消
_timer = Timer.periodic(Duration(seconds: 2), (timer) {
print('_timer05() -> Timer.periodic() -> Timer.tick -> ${timer.tick} -> Timer.isActive -> ${timer.isActive}');
});
_timer.cancel();
ACETimerButton 自定義計(jì)時(shí)器
????小菜嘗試了一個(gè)簡單的計(jì)時(shí)器,類似于獲取驗(yàn)證碼按鈕歹叮;timeout 為倒計(jì)時(shí)時(shí)長跑杭,color 用于自定義文本顏色,preName 為文本內(nèi)容咆耿;
ACETimerButton(this.timeout, {this.color, this.preName});
????整個(gè)定義過程很簡單德谅,只需在按鈕點(diǎn)擊時(shí)更新按鈕文本內(nèi)容以及進(jìn)行 Timer 周期性倒計(jì)時(shí)計(jì)算,并在倒計(jì)時(shí)結(jié)束和 Widget 銷毀時(shí)及時(shí)取消并銷毀 Timer 即可萨螺;
class ACETimerButton extends StatefulWidget {
final int timeout;
final Color color;
final String preName;
ACETimerButton(this.timeout, {this.color, this.preName});
@override
_ACETimerButtonState createState() => _ACETimerButtonState();
}
class _ACETimerButtonState extends State<ACETimerButton> {
Timer _timer;
int _timeOut;
String _name;
bool _isClick = false;
@override
Widget build(BuildContext context) => GestureDetector(
onTap: () {
if (!_isClick) {
_startTimer();
}
_isClick = true;
},
child: Container(
padding: EdgeInsets.all(6.0),
decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.2),
borderRadius: BorderRadius.circular(4.0)),
child: Center(child: Text(_name ?? 'click', style: TextStyle(color: widget.color ?? Colors.blue, fontSize: 16.0)))));
@override
void initState() {
super.initState();
_name = widget.preName;
_timeOut = widget.timeout;
}
_startTimer() {
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
setState(() {
_timeOut--;
_name = '$_timeOut s';
});
if (_timeOut == 0) {
_cancelTimer();
_isClick = false;
_name = widget.preName;
_timeOut = widget.timeout;
}
});
}
_cancelTimer() {
if (_timer != null) {
_timer.cancel();
_timer = null;
}
_isClick = false;
}
@override
void dispose() {
super.dispose();
_cancelTimer();
}
}
????Timer 案例源碼
????小菜對(duì) Timer 計(jì)時(shí)器的學(xué)習(xí)暫時(shí)告一段落窄做,對(duì)于 ACETimerButton 自定義計(jì)時(shí)器按鈕還不夠完善;如有錯(cuò)誤慰技,請(qǐng)多多指導(dǎo)椭盏!
來源: 阿策小和尚