Flutter:倒数计时器
Flutter: Countdown Timer
我正在尝试创建一个计时器应用程序,该应用程序具有针对不同任务的多个倒数计时器。我面临的问题是,如果我启动一次性计时器并按下后退按钮,计时器就会停止。所以我想要,该计时器 运行 直到它被暂停或计时器结束并提醒用户或应用程序被销毁。帮助我如何使用 Flutter 执行此操作?
任何示例代码都会受到赞赏?
CountDownController _controller = CountDownController();
CircularCountDownTimer(
width: MediaQuery.of(context).size.width / 6,
height: MediaQuery.of(context).size.width / 6,
duration: 120,
fillColor: Colors.green,
ringColor: Colors.white,
controller: _controller,
backgroundColor: Colors.white54,
strokeWidth: 10.0,
strokeCap: StrokeCap.round,
isTimerTextShown: true,
isReverse: false,
onComplete: () {
Notify();
},
textStyle: TextStyle(fontSize: 20.0, color:
Colors.black),
),
弹回时,小部件中的任何“状态”都将被销毁。
你可以采取三种方法来防止“状态”被破坏(或内存释放):
- 使用静态 属性
- Provider
使用状态管理器
- 通过静态实例使用状态管理器
还有很多方法可以管理你的状态,这里就不多说了,详见this repo
静态属性
静态 属性 类似于 class 之外的变量,例如:
// prefix "_" for private variable
const _myStaticVar = 'hello world';
class MyWidget {}
相反,它是基于 class 的变量。这意味着它可以帮助您更多地描述变量。像classDog
可以有静态的属性static final footShouldHave = 4
。基于 Class 的编程很受欢迎,因为它可以管理您的状态和 class“内部”的任何逻辑操作,并使其更易于理解和编码。
当 class 被销毁(内存释放)时,class 中的任何“状态”都应该从堆栈中弹出,而不是静态的。您可以通过了解编译器的工作原理来查看更多详细信息。
对于你的情况,你可以这样做:
class MyTimer extends StatlessWidget {
static DateTime? starter;
Widget build(context) {
if (starter == null) {
starter = DateTime.now();
}
final secondPass = (DateTime.now().millisecondsSinceEpoch - starter!.millisecondsSinceEpoch) / 1000;
final secondLeft = 60 - secondPass;
return Text(secondLeft.toString());
}
}
通过Provider
提供状态管理器
Provider
是为 flutter 制作的,也由 flutter 团队维护。通过从 context
.
访问它可以让您轻松管理 class
您还可以设置 class 创建的方式。
lazy
,只在需要时创建
- 在
future
中创建
- ...
在你的情况下,它应该是这样的:
- 建立你的帮手class
TimerManager
class TimerManager {
final DateTime? starter;
void startIfNeed() {
if (starter != null) {
starter = DateTime.now();
}
}
num get secondLeft => 60 - (DateTime.now().millisecondsSinceEpoch - starter!.millisecondsSinceEpoch) / 1000
}
- 绑定
Provider
class Homepage extends statelessWidget {
Widget build(context) {
return TextButton(
onPressed: () => navigateToTimer(context),
child: Text('go'),
);
}
void navigateToTimer(Build context) {
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => MyTimer()),
);
}
}
void main() {
runApp(MaterialApp(
home: Provider<TimerManager>(
create: () => TimerManager(),
child: Homepage(),
)
));
}
- 从你的
context
获取它。
现在,当您的小部件发布时,它仍然存在于父级 context
中(如果它们确实存在父级)。
// remember to import provider to able `context.read()`.
// see more detail in document.
import 'package:provider/provider.dart';
class MyTimer extends StatlessWidget {
Widget build(context) {
final manager = context.read<TimerManager>();
manager.startIfNeed();
return Text(manager.secondLeft.toString());
}
}
静态实例
1 和 2 的一种组合方法。
class TimerManager {
// make it singleton
static final TimerManager instance = TimerManager._();
// It is now private constructor
const TimerManager._();
...
}
只需在您的小部件中调用它
class MyTimer extends StatlessWidget {
Widget build(context) {
TimerManager.instance.startIfNeed();
return Text(TimerManager.instance.secondLeft.toString());
}
}
总结
一般情况下没有最好的方法来保持你的状态,但在你的情况下,我推荐Provider
方法。
我正在尝试创建一个计时器应用程序,该应用程序具有针对不同任务的多个倒数计时器。我面临的问题是,如果我启动一次性计时器并按下后退按钮,计时器就会停止。所以我想要,该计时器 运行 直到它被暂停或计时器结束并提醒用户或应用程序被销毁。帮助我如何使用 Flutter 执行此操作?
任何示例代码都会受到赞赏?
CountDownController _controller = CountDownController();
CircularCountDownTimer(
width: MediaQuery.of(context).size.width / 6,
height: MediaQuery.of(context).size.width / 6,
duration: 120,
fillColor: Colors.green,
ringColor: Colors.white,
controller: _controller,
backgroundColor: Colors.white54,
strokeWidth: 10.0,
strokeCap: StrokeCap.round,
isTimerTextShown: true,
isReverse: false,
onComplete: () {
Notify();
},
textStyle: TextStyle(fontSize: 20.0, color:
Colors.black),
),
弹回时,小部件中的任何“状态”都将被销毁。
你可以采取三种方法来防止“状态”被破坏(或内存释放):
- 使用静态 属性
- Provider 使用状态管理器
- 通过静态实例使用状态管理器
还有很多方法可以管理你的状态,这里就不多说了,详见this repo
静态属性
静态 属性 类似于 class 之外的变量,例如:
// prefix "_" for private variable
const _myStaticVar = 'hello world';
class MyWidget {}
相反,它是基于 class 的变量。这意味着它可以帮助您更多地描述变量。像classDog
可以有静态的属性static final footShouldHave = 4
。基于 Class 的编程很受欢迎,因为它可以管理您的状态和 class“内部”的任何逻辑操作,并使其更易于理解和编码。
当 class 被销毁(内存释放)时,class 中的任何“状态”都应该从堆栈中弹出,而不是静态的。您可以通过了解编译器的工作原理来查看更多详细信息。
对于你的情况,你可以这样做:
class MyTimer extends StatlessWidget {
static DateTime? starter;
Widget build(context) {
if (starter == null) {
starter = DateTime.now();
}
final secondPass = (DateTime.now().millisecondsSinceEpoch - starter!.millisecondsSinceEpoch) / 1000;
final secondLeft = 60 - secondPass;
return Text(secondLeft.toString());
}
}
通过Provider
提供状态管理器
Provider
是为 flutter 制作的,也由 flutter 团队维护。通过从 context
.
您还可以设置 class 创建的方式。
lazy
,只在需要时创建- 在
future
中创建
- ...
在你的情况下,它应该是这样的:
- 建立你的帮手class
TimerManager
class TimerManager {
final DateTime? starter;
void startIfNeed() {
if (starter != null) {
starter = DateTime.now();
}
}
num get secondLeft => 60 - (DateTime.now().millisecondsSinceEpoch - starter!.millisecondsSinceEpoch) / 1000
}
- 绑定
Provider
class Homepage extends statelessWidget {
Widget build(context) {
return TextButton(
onPressed: () => navigateToTimer(context),
child: Text('go'),
);
}
void navigateToTimer(Build context) {
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => MyTimer()),
);
}
}
void main() {
runApp(MaterialApp(
home: Provider<TimerManager>(
create: () => TimerManager(),
child: Homepage(),
)
));
}
- 从你的
context
获取它。
现在,当您的小部件发布时,它仍然存在于父级 context
中(如果它们确实存在父级)。
// remember to import provider to able `context.read()`.
// see more detail in document.
import 'package:provider/provider.dart';
class MyTimer extends StatlessWidget {
Widget build(context) {
final manager = context.read<TimerManager>();
manager.startIfNeed();
return Text(manager.secondLeft.toString());
}
}
静态实例
1 和 2 的一种组合方法。
class TimerManager {
// make it singleton
static final TimerManager instance = TimerManager._();
// It is now private constructor
const TimerManager._();
...
}
只需在您的小部件中调用它
class MyTimer extends StatlessWidget {
Widget build(context) {
TimerManager.instance.startIfNeed();
return Text(TimerManager.instance.secondLeft.toString());
}
}
总结
一般情况下没有最好的方法来保持你的状态,但在你的情况下,我推荐Provider
方法。