前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Flutter 专题】135 图解 Timer & ACETimerButton 自定义计时器按钮

【Flutter 专题】135 图解 Timer & ACETimerButton 自定义计时器按钮

作者头像
阿策小和尚
发布2021-08-25 10:26:24
9620
发布2021-08-25 10:26:24
举报
文章被收录于专栏:阿策小和尚阿策小和尚

和尚在学习 Flutter 过程中,可能会遇到倒计时等需求,此时需要用到 Timer 计时器,和尚简单尝试一下;

Timer

Timer 可以作为一次或者重复触发的倒计时计时器;Timer 作为一个抽象类,提供了两种工厂方法进行调用;

案例尝试

1. Timer()
代码语言:javascript
复制
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 允许指定延迟时间之后执行,通过设置 Timeout 来指定延迟时间,之后通过 callback 回调对执行结果进行监听处理;

代码语言:javascript
复制
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()
代码语言:javascript
复制
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() 命名构造方法可得,该命名构造方法通过定时绑定回调进行再次 Timer 倒计时处理;

Timer.periodic() 可以重复性、周期性的进行倒计时,若不进行手动调用,则会一直关闭,即便页面关闭也会继续调用;

其中 Timer.tick 为调用次数,Timer.isActive 代表当前 Timer 是否处于活跃状态;

代码语言:javascript
复制
Timer.periodic(Duration(seconds: 2), (timer) {
  print('_timer02() -> Timer.periodic() -> Timer.tick -> ${timer.tick} -> Timer.isActive -> ${timer.isActive}');
});
3. Timer.run()
代码语言:javascript
复制
static void run(void Function() callback) {
    new Timer(Duration.zero, callback);
}

Timer 的执行为异步操作,Flutter 提供了便利的 Timer.run() 命名构造函数可以方便尽快执行,可以简单理解为倒计时为 0

和尚尝试了如下操作顺序,首先执行同步的 A -> B -> C,之后才会是异步的 run() 和 Duration.zero

代码语言:javascript
复制
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() 计时器可以通过 cancel() 来取消,尤其是在进行周期性的 Timer.periodic() 调用时,需要在合适的时机及时取消;和尚尝试在 Timer() 回调内取消和方法外回调两种方式;

4.1 Timer() 回调内取消
代码语言:javascript
复制
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 方法外取消
代码语言:javascript
复制
_timer = Timer.periodic(Duration(seconds: 2), (timer) {
  print('_timer05() -> Timer.periodic() -> Timer.tick -> ${timer.tick} -> Timer.isActive -> ${timer.isActive}');
});

_timer.cancel();

ACETimerButton 自定义计时器

和尚尝试了一个简单的计时器,类似于获取验证码按钮;timeout 为倒计时时长,color 用于自定义文本颜色,preName 为文本内容;

代码语言:javascript
复制
ACETimerButton(this.timeout, {this.color, this.preName});

整个定义过程很简单,只需在按钮点击时更新按钮文本内容以及进行 Timer 周期性倒计时计算,并在倒计时结束和 Widget 销毁时及时取消并销毁 Timer 即可;

代码语言:javascript
复制
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 案例源码


和尚对 Timer 计时器的学习暂时告一段落,对于 ACETimerButton 自定义计时器按钮还不够完善;如有错误,请多多指导!

来源:阿策小和尚

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-08-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 阿策小和尚 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Timer
    • 案例尝试
      • 1. Timer()
      • 2. Timer.periodic()
      • 3. Timer.run()
      • 4. cancel()
    • ACETimerButton 自定义计时器
    相关产品与服务
    验证码
    腾讯云新一代行为验证码(Captcha),基于十道安全栅栏, 为网页、App、小程序开发者打造立体、全面的人机验证。最大程度保护注册登录、活动秒杀、点赞发帖、数据保护等各大场景下业务安全的同时,提供更精细化的用户体验。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档