Flutter 135: 圖解 Timer & ACETimerButton 自定義計(jì)時(shí)器按鈕

????小菜在學(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)椭盏!

來源: 阿策小和尚

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市吻商,隨后出現(xiàn)的幾起案子掏颊,更是在濱河造成了極大的恐慌,老刑警劉巖艾帐,帶你破解...
    沈念sama閱讀 216,744評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件乌叶,死亡現(xiàn)場離奇詭異改化,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)枉昏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來揍鸟,“玉大人兄裂,你說我怎么就攤上這事⊙粼澹” “怎么了晰奖?”我有些...
    開封第一講書人閱讀 163,105評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長腥泥。 經(jīng)常有香客問我匾南,道長,這世上最難降的妖魔是什么蛔外? 我笑而不...
    開封第一講書人閱讀 58,242評(píng)論 1 292
  • 正文 為了忘掉前任蛆楞,我火速辦了婚禮,結(jié)果婚禮上夹厌,老公的妹妹穿的比我還像新娘豹爹。我一直安慰自己,他們只是感情好矛纹,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,269評(píng)論 6 389
  • 文/花漫 我一把揭開白布臂聋。 她就那樣靜靜地躺著,像睡著了一般或南。 火紅的嫁衣襯著肌膚如雪孩等。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,215評(píng)論 1 299
  • 那天采够,我揣著相機(jī)與錄音肄方,去河邊找鬼。 笑死吁恍,一個(gè)胖子當(dāng)著我的面吹牛扒秸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播冀瓦,決...
    沈念sama閱讀 40,096評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼伴奥,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了翼闽?” 一聲冷哼從身側(cè)響起拾徙,我...
    開封第一講書人閱讀 38,939評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎感局,沒想到半個(gè)月后尼啡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體暂衡,經(jīng)...
    沈念sama閱讀 45,354評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,573評(píng)論 2 333
  • 正文 我和宋清朗相戀三年崖瞭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了狂巢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,745評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡书聚,死狀恐怖唧领,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情雌续,我是刑警寧澤斩个,帶...
    沈念sama閱讀 35,448評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站驯杜,受9級(jí)特大地震影響受啥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鸽心,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,048評(píng)論 3 327
  • 文/蒙蒙 一滚局、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧再悼,春花似錦核畴、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至莺奸,卻和暖如春丑孩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背灭贷。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評(píng)論 1 269
  • 我被黑心中介騙來泰國打工温学, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人甚疟。 一個(gè)月前我還...
    沈念sama閱讀 47,776評(píng)論 2 369
  • 正文 我出身青樓仗岖,卻偏偏與公主長得像,于是被迫代替她去往敵國和親览妖。 傳聞我的和親對(duì)象是個(gè)殘疾皇子轧拄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,652評(píng)論 2 354

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