创建一个倒计时器,为列表中的每个值每5秒打印一次剩余时间
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了创建一个倒计时器,为列表中的每个值每5秒打印一次剩余时间相关的知识,希望对你有一定的参考价值。
我正在尝试在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);
}
每次运行时,持续时间由_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);
}
除非另有说明,否则结果应如下所示,行之间的暂停时间为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
答案
Dart / Flutter支持使用CountDownTimer进行倒计时。下面是两个示例,一个没有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();
});
}
例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),
)),
);
}
}
另一答案
试试这个!
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'NonStopIO',
theme: new ThemeData(
primarySwatch: Colors.red,
),
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var _sequence = [10, 10, 8];
@override
void initState() {
super.initState();
startTimer(0);
}
startTimer(int index) async {
if (index < _sequence.length) {
print("Sequence $index - countdown : ${_sequence[index]} ");
new Timer.periodic(new Duration(seconds: 5), (timer) {
if ((_sequence[index] / 5) >= timer.tick) {
print("${_sequence[index] - timer.tick * 5}");
} else {
timer.cancel();
startTimer(index + 1);
}
});
}
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('NonStopIO'),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(
'Counter',
),
new Text(
'',
),
],
),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
另一答案
// Start the periodic timer which prints something every 5 seconds
Timer timer = new Timer.periodic(new Duration(seconds: 5), (timer) {
print('Something');
});
// Stop the periodic timer using another timer which runs only once after specified duration
new Timer(new Duration(minutes: 1), () {
timer.cancel();
});
另一答案
我找到了另一个满足你的要求的答案。试试这个,
import 'package:flutter/material.dart';
import 'package:quiver/async.dart';
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
new CountdownTimer(new Duration(minutes: 1), new Duration(seconds: 5)).listen((data) {
print('Something');
print('Remaining time: ${data.remaining.inSeconds}');
});
super.initState();
}
@override
Widget build(BuildContext context) {
return new Container(
);
}
}
以上是关于创建一个倒计时器,为列表中的每个值每5秒打印一次剩余时间的主要内容,如果未能解决你的问题,请参考以下文章
位置值每隔几秒更改一次 - navigator.geolocation.getCurrentPosition