skip to Main Content

can you please help me with this code . i made a timer .

i want the timer stops when it’s value gets 1 ;

but it doesn’t . i don’t know where is the problem.

please help me . thank you.

here is the result in emulator:

enter image description here

here is my whole code:

class _MyHomeState extends State<MyHome> {
  double progress = 0;
  void startTimer() {
    Timer.periodic(const Duration(seconds: 1), (timer) {
      setState(() {
        if (progress == 1) {
          timer.cancel();
        } else {
          progress += 0.1;
        }
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Stack(
            alignment: Alignment.center,
            children: [
              Text(progress.toStringAsFixed(1)),
              SizedBox(
                height: 300,
                width: 300,
                child: CircularProgressIndicator(
                  value: progress,
                  color: Colors.deepOrange,
                ),
              )
            ],
          ),
          const SizedBox(
            height: 50,
          ),
          ElevatedButton(
              onPressed: () {
                setState(() {
                  progress = 0;
                  startTimer();
                });
              },
              child: const Text('Start'))
        ],
      ),
    );
  }
}

2

Answers


  1. It’s because of floating point error. In software development decimals can’t be used in calculations with 100% accuracy. You can’t guarantee that 0.1 + 0.1 = 0.2. The problem here is that progress never will equal 1. If you print progress in your else branch of the timer you will see that it shows:

    0.1
    0.2
    0.30000000000000004
    0.4
    0.5
    0.6
    0.7
    0.7999999999999999
    0.8999999999999999
    0.9999999999999999
    1.0999999999999999
    1.2
    1.3
    

    To solve it simply don’t check for one but check if it’s higher than 0.99 for example so like

            if (progress > 0.99) {
              timer.cancel();
            } else {
              progress += 0.1;
            }
    
    Login or Signup to reply.
  2. If the timer doesn’t stop when its value reaches 1, it might be due to the condition inside the timer’s callback not being met exactly due to floating-point arithmetic inaccuracies. When you increment progress by 0.1, it might not reach exactly 1 due to the way floating-point numbers are represented in computer arithmetic. Thus, the condition if (progress == 1) may never be true, causing the timer to not cancel as expected.

    A better approach is to check if the progress is greater than or equal to 1. This will ensure that the timer stops even if there’s a slight arithmetic inaccuracy. Here’s how you can adjust the startTimer method:

    void startTimer() {
      Timer.periodic(const Duration(seconds: 1), (timer) {
        setState(() {
          if (progress >= 1) { // Change this line
            timer.cancel();
          } else {
            progress += 0.1;
            if (progress > 1) { // Ensure progress does not exceed 1
              progress = 1;
            }
          }
        });
      });
    }

    With this adjustment, the timer will cancel as soon as progress is greater than or equal to 1, ensuring that the timer stops. Also, by checking if progress exceeds 1 after incrementing it and setting it back to 1 if it does, you can avoid having a progress value that exceeds the maximum expected value, ensuring that the CircularProgressIndicator behaves as expected.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search