创建一个倒数计时器,每 5 秒为列表中的每个值打印一次剩余时间

Sim*_*ler 2 dart flutter

我正在尝试在 Flutter 中创建一个倒数计时器,它每 5 秒打印一次剩余时间,直到计时器用完,然后为值列表中的下一个值运行相同的倒数计时器。

下面的递归函数接近了,但它在进入下一个值之前等待“迭代”,List即使剩余时间更少Timer

import 'dart:async';

Future main() async {
  final _sequence = [21, 10, 8];
  final _iteration = 5;

  void _countdown(seq) async {
    if (seq.length > 0) {
      var duration = seq[0];
      print('Starting at $duration');
      Timer.periodic(Duration(seconds: _iteration), (timer) {
        var remaining = duration - timer.tick * _iteration;
        if (remaining >= 0) {
          print('$duration, $remaining');
        } else {
          timer.cancel();
          _countdown(seq.sublist(1));
        }
      });
    }
  }

  _countdown(_sequence);
}
Run Code Online (Sandbox Code Playgroud)

每次运行时,持续时间由_sequence列表中的值定义。

即使使用CountdownTimer(而不是Timer.periodic) 也有同样的问题,当剩余值小于迭代时等待太久:

import 'package:quiver/async.dart';

main() {
  final _sequence = [21, 10, 8];
  final _iteration = 5;

  void _countdown(seq) {
    if (seq.length > 0) {
      var duration = seq[0];
      print('Starting at $duration');
      CountdownTimer countdownTimer = CountdownTimer(
        Duration(seconds: duration),
        Duration(seconds: _iteration),
      );

      var sub = countdownTimer.listen(null);
      sub.onData((timer) {
        if (timer.remaining > Duration(seconds: 0)) {
          print('$duration, ${timer.remaining.inSeconds}');
        } else {
          sub.cancel();
          _countdown(seq.sublist(1));
        }
      });
    }
  }

  _countdown(_sequence);
}
Run Code Online (Sandbox Code Playgroud)

结果应该是这样的,行之间有 5 秒的停顿,除非另有说明:

Starting at 21
21, 16
21, 11
21, 6
21, 1          <-- This one should only pause 1 second before continuing
Starting at 10
10, 5
10, 0          <-- This one should immediately continue
Starting at 8
8, 3           <-- This one should only pause 3 seconds before continuing
Run Code Online (Sandbox Code Playgroud)

Phu*_*ran 6

Dart/Flutter 支持使用 CountDownTimer 进行倒计时。下面是 2 个例子,一个没有 UI,一个在屏幕中心有一个简单的文本(超时 = 10 秒,步长 = 1 秒,你可以更改为任何你想要的)

示例 1:

import 'package:quiver/async.dart';

void main() {
  const timeOutInSeconds = 10;
  const stepInSeconds = 2;
  int currentNumber = 0;

  CountdownTimer countDownTimer = new CountdownTimer(
      new Duration(seconds: timeOutInSeconds),
      new Duration(seconds: stepInSeconds));

  var sub = countDownTimer.listen(null);
  sub.onData((duration) {
    currentNumber += stepInSeconds;
    int countdownNumber = timeOutInSeconds - currentNumber;
    // Make it start from the timeout value
    countdownNumber += stepInSeconds;
    print('Your message here: $countdownNumber');
  });

  sub.onDone(() {
    print("I'm done");

    sub.cancel();
  });
}
Run Code Online (Sandbox Code Playgroud)

示例 2:

import 'package:flutter/material.dart';
import 'package:quiver/async.dart';

void main() {
  runApp(new MaterialApp(home: new CountdownTimerPage()));
}

class CountdownTimerPage extends StatefulWidget {
  @override
  CountdownTimerPageState createState() => new CountdownTimerPageState();
}

class CountdownTimerPageState extends State<CountdownTimerPage> {
  final timeOutInSeconds = 10;
  final stepInSeconds = 2;
  int currentNumber = 0;

  CountdownTimerPageState() {
    setupCountdownTimer();
  }

  setupCountdownTimer() {
    CountdownTimer countDownTimer = new CountdownTimer(
        new Duration(seconds: timeOutInSeconds),
        new Duration(seconds: stepInSeconds));

    var sub = countDownTimer.listen(null);
    sub.onData((duration) {
      currentNumber += stepInSeconds;

      this.onTimerTick(currentNumber);
      print('Your message here: $currentNumber');
    });

    sub.onDone(() {
      print("I'm done");

      sub.cancel();
    });
  }

  void onTimerTick(int currentNumber) {
    setState(() {
      currentNumber = currentNumber;
    });
  }

  @override
  Widget build(BuildContext context) {
    int number = timeOutInSeconds - currentNumber;
    // Make it start from the timeout value
    number += stepInSeconds;
    return new Scaffold(
      body: new Center(
          child: new Text(
        "Your message here: $number",
        style: new TextStyle(color: Colors.red, fontSize: 25.0),
      )),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)