Timer.periodic 无法与提供商一起正常工作
Timer.periodic does not work correctly with provider
我正在尝试在扩展 class ChangeNotifier
的 class 中使用 class Timer
的方法 periodic
(包 Provider)使我的变量 time
每秒减少。
如果我不添加重绘所有占据 time
属性 的小部件的 NotifyListeners
方法,这将正常工作,例如:
class PriceProvider extends ChangeNotifier{
int _time = 60;
int get time{
return _time;
}
void chronometer(){//method which activate the timer
Timer _timer = Timer.periodic(const Duration(seconds: 1), (Timer timer){
print(DateTime.now());//I print the date so you can see how often the code is executed
_time += -1;//decrease time
if(_time == 0){
_time = 60;
}
// notifyListeners();
});
}
}
控制台输出(每秒正确运行):
另一方面,如果我取消注释 NotifyListeners
方法,代码开始以指数方式每秒执行越来越多的次数(例如,首先执行一次,然后执行两次,然后执行 5 次,然后执行 9 次,然后很快):
这是我调用方法 chronometer
:
的代码
class PriceWithClock extends StatelessWidget {
@override
Widget build(BuildContext context) {
PriceProvider priceProvider = Provider.of<PriceProvider>(context);
priceProvider.chronometer();
return CircularPercentIndicator(
radius: 100.0,
lineWidth: 5.0,
percent: 1-priceProvider.time/60,
center: Text("00:${priceProvider.time}"),
),
);
}
}
您不应该将 priceProvider.chronometer();
放在构建方法中,因为它将在每个 PriceWithClock
小部件构建时执行。在你的情况下,它会每秒发生一次。
您可以做的是创建一个有状态的小部件并在 initState()
方法中触发计时器:
class PriceWithClock extends StatefulWidget {
@override
State<StatefulWidget> createState() => _PriceWithClockState();
}
class _PriceWithClockState extends State<PriceWithClock> {
@override
void initState() {
super.initState();
context.read<PriceProvider>().chronometer();
}
@override
Widget build(BuildContext context) {
...
}
}
至于 build
方法,您可以使用 context.watch
Provider 扩展方法来监听更新后的 time
值:
class _PriceWithClockState extends State<PriceWithClock> {
...
@override
Widget build(BuildContext context) {
final time = context.watch<PriceProvider>().time;
return CircularPercentIndicator(
radius: 100.0,
lineWidth: 5.0,
percent: 1 - time / 60,
center: Text("00:$time"),
);
}
}
最终结果如下所示:
class PriceWithClock extends StatefulWidget {
@override
State<StatefulWidget> createState() => _PriceWithClockState();
}
class _PriceWithClockState extends State<PriceWithClock> {
@override
void initState() {
super.initState();
context.read<PriceProvider>().chronometer();
}
@override
Widget build(BuildContext context) {
final time = context.watch<PriceProvider>().time;
return CircularPercentIndicator(
radius: 100.0,
lineWidth: 5.0,
percent: 1 - time / 60,
center: Text("00:$time"),
);
}
}
我正在尝试在扩展 class ChangeNotifier
的 class 中使用 class Timer
的方法 periodic
(包 Provider)使我的变量 time
每秒减少。
如果我不添加重绘所有占据 time
属性 的小部件的 NotifyListeners
方法,这将正常工作,例如:
class PriceProvider extends ChangeNotifier{
int _time = 60;
int get time{
return _time;
}
void chronometer(){//method which activate the timer
Timer _timer = Timer.periodic(const Duration(seconds: 1), (Timer timer){
print(DateTime.now());//I print the date so you can see how often the code is executed
_time += -1;//decrease time
if(_time == 0){
_time = 60;
}
// notifyListeners();
});
}
}
控制台输出(每秒正确运行):
另一方面,如果我取消注释 NotifyListeners
方法,代码开始以指数方式每秒执行越来越多的次数(例如,首先执行一次,然后执行两次,然后执行 5 次,然后执行 9 次,然后很快):
这是我调用方法 chronometer
:
class PriceWithClock extends StatelessWidget {
@override
Widget build(BuildContext context) {
PriceProvider priceProvider = Provider.of<PriceProvider>(context);
priceProvider.chronometer();
return CircularPercentIndicator(
radius: 100.0,
lineWidth: 5.0,
percent: 1-priceProvider.time/60,
center: Text("00:${priceProvider.time}"),
),
);
}
}
您不应该将 priceProvider.chronometer();
放在构建方法中,因为它将在每个 PriceWithClock
小部件构建时执行。在你的情况下,它会每秒发生一次。
您可以做的是创建一个有状态的小部件并在 initState()
方法中触发计时器:
class PriceWithClock extends StatefulWidget {
@override
State<StatefulWidget> createState() => _PriceWithClockState();
}
class _PriceWithClockState extends State<PriceWithClock> {
@override
void initState() {
super.initState();
context.read<PriceProvider>().chronometer();
}
@override
Widget build(BuildContext context) {
...
}
}
至于 build
方法,您可以使用 context.watch
Provider 扩展方法来监听更新后的 time
值:
class _PriceWithClockState extends State<PriceWithClock> {
...
@override
Widget build(BuildContext context) {
final time = context.watch<PriceProvider>().time;
return CircularPercentIndicator(
radius: 100.0,
lineWidth: 5.0,
percent: 1 - time / 60,
center: Text("00:$time"),
);
}
}
最终结果如下所示:
class PriceWithClock extends StatefulWidget {
@override
State<StatefulWidget> createState() => _PriceWithClockState();
}
class _PriceWithClockState extends State<PriceWithClock> {
@override
void initState() {
super.initState();
context.read<PriceProvider>().chronometer();
}
@override
Widget build(BuildContext context) {
final time = context.watch<PriceProvider>().time;
return CircularPercentIndicator(
radius: 100.0,
lineWidth: 5.0,
percent: 1 - time / 60,
center: Text("00:$time"),
);
}
}