Home > Enterprise >  Timer.periodic does not work correctly with provider
Timer.periodic does not work correctly with provider

Time:03-17

I am trying to use the method periodic of the class Timer inside a class which extends of the class ChangeNotifier (of the package Salida por consola

On the other hand, if I uncomment the NotifyListeners method, the code starts executing more and more times per second exponentially (for example, first it executes once, then twice, then 5, then 9 and so on): Salida por consola

Here is the code where I call the method 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}"),
     ),
    );
  }
}

CodePudding user response:

You should not put the priceProvider.chronometer(); inside the build method since it will be executed on every PriceWithClock widget build. And in your case, it would happen every second.

What you can do, is create a Stateful widget and trigger the chronometer inside the initState() method:

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) {
    ...
  }
}

As for the build method, you could use the context.watch Provider extension method to listen to the updated time value:

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"),
    );
  }
}

The final result looks like this:

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"),
    );
  }
}
  • Related