当前位置:   article > 正文

Flutter开发之倒计时/定时器(30)_dart 倒计时

dart 倒计时

倒计时/定时器在移动应用开发中比较常见的功能,比如启动时的广告倒计时、比如弹框倒计时、比如定时1秒后跳转、获取验证码等等。今天就认识一下Flutter中的倒计时/定时器。

一般有两种场景:

我只需要你在指定时间结束后回调告诉我。回调只需要一次。
我需要你在指定时间结束后回调告诉我。回调可能多次。
  • 1
  • 2

Timer 类存在于dart:async内,所以我们需要先导入

import 'dart:async';
  • 1
回调一次的定时器

Timer 的构造也很简单,一个时长Duration 一个到时之后执行的任务callback,如下图,他的构造方法
在这里插入图片描述

const timeout = const Duration(seconds: 5);
    print('currentTime ='+DateTime.now().toString());
    Timer(timeout, () {
      //到时回调
      print('after 5s Time ='+DateTime.now().toString());
    });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这里我们设置了超时时间为 5 秒。然后启动一个定时器,等到 5 秒时候到了,就会执行回调方法。

我们在定时器启动之前和之后都加上了打印日志,控制台打印输出如下:

I/flutter (15245): currentTime =2019-07-17 13:58:52.281287
I/flutter (15245): after 5s Time =2019-07-17 13:58:57.284234
  • 1
  • 2
回调多次的定时器

回调多次的定时器用法和回调一次的差不多,区别有下面两点:

API 调用不同
需要手动取消,否则会一直回调,因为是周期性的
  • 1
  • 2
int count = 0;
const period = const Duration(seconds: 1);
print('currentTime='+DateTime.now().toString());
Timer.periodic(period, (timer) {
  //到时回调
  print('afterTimer='+DateTime.now().toString());
  count++;
  if (count >= 5) {
    //取消定时器,避免无限回调
    timer.cancel();
    timer = null;
  }
});

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

这里我们的功能是每秒回调一次,当达到 5 秒后取消定时器,一共 回调了 5 次。
控制台输出如下:

I/flutter (15245): currentTime=2019-07-17 14:07:21.147541
I/flutter (15245): afterTimer=2019-07-17 14:07:22.166514
I/flutter (15245): afterTimer=2019-07-17 14:07:23.165105
I/flutter (15245): afterTimer=2019-07-17 14:07:24.165862
I/flutter (15245): afterTimer=2019-07-17 14:07:25.167847
I/flutter (15245): afterTimer=2019-07-17 14:07:26.165679
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

注意⚠️:得在合适时机取消定时器,否则会一直回调

实例运用
业务场景

服务器返回一个时间,你根据服务器的时间和当前时间的对比,显示倒计时,倒计时的时间在一天之内,超过一天显示默认文案即可。在一天之内,所以显示的文案就是从 00:00:00 到 23:59:59。

基本思路:

首先我们需要获得剩余时间,接着启动一个 1 秒的周期性定时器,然后每隔一秒更新一下文案。此外还加了开始和停止的逻辑。

代码:
import 'package:flutter/material.dart';
import 'dart:async';

class TimerTest extends StatefulWidget {
  TimerTest({Key key, this.title}) : super(key: key);
  final String title;
  @override
  createState() => new _TimerTestState();
}

class _TimerTestState extends State<TimerTest> {

  Timer _timer;
  int seconds = 0;
  bool _timeState = true;
  String _title = 'start';
  String _content = '00:00:00';

  @override
  Widget build(BuildContext context) {

    print('build');

    _content = constructTime(seconds);

    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Timer test'),
      ),

      body: Center(
        child:Column(

          children: <Widget>[

            SizedBox(height:25.0),
            Text("定时器倒计时练习"),

            SizedBox(height: 25.0),

            RaisedButton(
              onPressed: _incrementCounter,
              child: new Text('只执行一次'),
            ),

            SizedBox(height: 20.0),

            RaisedButton(
              onPressed: _tickTest,
              child: new Text('周期性Tick'),
            ),


            SizedBox(height: 20.0),
            RaisedButton(
              onPressed: countDownTest,
              child: new Text('$_title'),
            ),

            SizedBox(height: 20.0),
            Text("$_content",style: TextStyle(color: Colors.red,fontSize: 30),),

          ],

        ),
      ),

    );
  }


  //时间格式化,根据总秒数转换为对应的 hh:mm:ss 格式
  String constructTime(int seconds) {
    int hour = seconds ~/ 3600;
    int minute = seconds % 3600 ~/ 60;
    int second = seconds % 60;
    return formatTime(hour) + ":" + formatTime(minute) + ":" + formatTime(second);
  }

  //数字格式化,将 0~9 的时间转换为 00~09
  String formatTime(int timeNum) {
    return timeNum < 10 ? "0" + timeNum.toString() : timeNum.toString();
  }

  // 初始化方法。先于build执行
  @override
  void initState() {
    super.initState();

    print('initState');
  }

  void countDownTest(){

    _timeState = !_timeState;
    setState(() {
      if (_timeState) {
        _title = 'start';
      } else {
        _title = 'stop';
      }
    });

    if (!_timeState) {
      //获取当期时间
      var now = DateTime.now();
      //获取 2 分钟的时间间隔
      var twoHours = now.add(Duration(minutes: 2)).difference(now);
      //获取总秒数,2 分钟为 120 秒
      seconds = twoHours.inSeconds;
      startTimer();
    } else {
      seconds = 0;
      cancelTimer();
    }
  }

  void startTimer() {
    //设置 1 秒回调一次
    const period = const Duration(seconds: 1);
    _timer = Timer.periodic(period, (timer) {
      //更新界面
      setState(() {
        //秒数减一,因为一秒回调一次
        seconds--;
      });
      if (seconds == 0) {
        //倒计时秒数为0,取消定时器
        cancelTimer();
      }
    });
  }

  void cancelTimer() {
    if (_timer != null) {
      _timer.cancel();
      _timer = null;
    }
  }

  @override
  void dispose() {
    cancelTimer();
    // 相当于dealloc
    super.dispose();
  }
}



void _incrementCounter() {
  const timeout = const Duration(seconds: 5);
  print('currentTime ='+DateTime.now().toString());
  Timer(timeout, () {
    //到时回调
    print('after 5s Time ='+DateTime.now().toString());
  });
}

_tickTest() {
  int count = 0;
  const period = const Duration(seconds: 1);
  print('currentTime='+DateTime.now().toString());
  Timer.periodic(period, (timer) {
    //到时回调
    print('afterTimer='+DateTime.now().toString());
    count++;
    if (count >= 5) {
      //取消定时器,避免无限回调
      timer.cancel();
      timer = null;
    }
  });
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174

效果如下:
在这里插入图片描述

总结:setState(){} 谁变set谁。这里set seconds

参考文章:

Flutter 快速上手定时器/倒计时及实战讲解

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/657967
推荐阅读
相关标签
  

闽ICP备14008679号