Flutter : Timer.periodic running multiple times in each iteration

2,566

The problem is that, every time you execute the run() method, a new timer is created and you listen for it, again. The old timer is not stopped, so it keeps firing. The solution is, before you create a timer, cancel the previous one. Something like this:

class _SnakePageState extends State<SnakePage> {
   Timer _myTimer;

void run() {
    this.running = true;
    _myTimer?.cancel(); //in case we have a timer, we'll cancel it.
    _myTimer = Timer.periodic(. // assing new timer to our variable.
        Duration(
          milliseconds: 500,
        ), (timer) {
      this.setState(() {
        this.iterates += 1;
        this.swipe = this.iterates.toString();
        for (var i = 0; i < this.snake.length; i++) {
          this.snake[i][0][1] += 1;
          if (this.snake[i][0][1] == 10) {
            this.snake[i][0][1] = 0;
          }
        }
      });
    });
  }

 
}
Share:
2,566
Priyanshu Jangra
Author by

Priyanshu Jangra

I am a high school student who got in touch with programming in 2020 and fell in love with it. Started with Python and looking forward to it.

Updated on December 27, 2022

Comments

  • Priyanshu Jangra
    Priyanshu Jangra over 1 year

    I am trying to make snake 2 in flutter. And I have used Timer.periodic() for game loop. And I tried specifying duration as 1 seconds. But the code inside the Timer.periodic() runs multiple times in a second. I also tried debugging (though I am terrible at that) and found that the code inside the Timer.periodic() ran multiple times without stepping out of it. Though while debugging this couild happen as the code pauses for input. But I'm not sure about anything .Here is my code -

    import 'dart:async';
    import 'dart:math';
    
    import 'package:flutter/material.dart';
    
    class SnakePage extends StatefulWidget {
      @override
      _SnakePageState createState() => _SnakePageState();
    }
    
    class _SnakePageState extends State<SnakePage> {
      int score = 0;
      String swipe = '';
      bool running = false;
      int iterates = 0;
      List snake = [
        [
          [4, 3],
          1,
          true
        ],
        [
          [4, 2],
          1,
          false
        ],
        [
          [4, 1],
          1,
          false
        ],
      ];
    
      // Convert radians to degree
      double radians(double degree) {
        return ((degree * 180) / pi);
      }
    
      void turn(moveEvent) {
           double angle = radians(moveEvent.delta.direction);
          if (angle >= -45 && angle <= 45) {
            this.swipe = 'Swipe Right';
          } else if (angle >= 45 && angle <= 135) {
            this.swipe = 'Swipe Down';
          } else if (angle <= -45 && angle >= -135) {
            this.swipe = 'Swipe Up';
          } else {
            this.swipe = 'Swipe Left';
          }
      }
    
      int toIndex(coOrdinates) {
        return ((coOrdinates[0] + 1) * 10) + coOrdinates[1];
      }
    
      void run() {
        this.running = true;
        Timer.periodic(
            Duration(
              milliseconds: 500,
            ), (timer) {
          this.setState(() {
            this.iterates += 1;
            this.swipe = this.iterates.toString();
            for (var i = 0; i < this.snake.length; i++) {
              this.snake[i][0][1] += 1;
              if (this.snake[i][0][1] == 10) {
                this.snake[i][0][1] = 0;
              }
            }
          });
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('WC'),
          ),
          body: Listener(
                onPointerMove: this.running
                    ? (moveEvent) => this.turn(moveEvent)
                    : (moveEvent) => this.run(),// Where the function is being called
                child: Container();
        );
      }
    }
    

    And please pardon me for code being a mess and not well commented. Any Help would be appreciated!

  • Priyanshu Jangra
    Priyanshu Jangra over 3 years
    But I have created a variable running and it is set true once the function is called and after that it calls turns function that has nothing to do with Timer.periodic(), though your given solution works for me, but I can't understand how the run function is called multiple times.
  • danypata
    danypata over 3 years
    @PriyanshuJangra Your running variable doesn't stop the execution of the timer block, if the timer is not canceled.