I am new to flutter and decided to build a simple timer app, that counts the number of seconds that have gone by since it's start and it ends up showing the wrong time. The timer starts off with 0, then increments to 1 and, from there on out it seems as if it is increasing exponentially.

main.dart

import 'package:flutter/material.dart';
import 'app.dart';

void main() => runApp(App());

app.dart

import 'package:flutter/material.dart';
import 'package:async/async.dart';
import 'clock_widget.dart';

class App extends StatelessWidget {
 @override

 Widget build(BuildContext context) {
  return MaterialApp(
  title: "Timer",
  home: Scaffold(
    appBar: AppBar(
      title: Text("Timer"),
      centerTitle: true,
    ),
    body: Row(
      mainAxisSize: MainAxisSize.max,
      crossAxisAlignment: CrossAxisAlignment.center,
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Column(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            ClockWidget(),
            Text("seconds", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 35),)
          ],
        )
      ],
    )
  ),
);
}

clock_widget.dart

import 'dart:async';
import 'package:flutter/material.dart';

class ClockWidget extends StatefulWidget {
  @override
  ClockWidgetState createState() => ClockWidgetState();
}

class ClockWidgetState extends State<ClockWidget> {
  @override
  int _secondCount = 0;

  Widget build(BuildContext context) {
    Timer.periodic(Duration(seconds: 1), (Timer t) => (setState(() {_secondCount+=1;})));
    print("${_secondCount}");
    return Text("${_secondCount}", style: TextStyle(fontSize: 75, color: Color.fromRGBO(30, 144, 255, 1)),);
  }
}

I have tried numberous methods but to me this seemed like the simplest one and logically it seems correct. After every second setState is called which increments _secondsCount.

The app's second count hardly 15 seconds after running it.

1

There are 1 best solutions below

1
On BEST ANSWER

You are currently defining new Timers every second. Each of these timers is incrementing the number of seconds.

You want to define your Timer only once and outside of the build method.

  1. Create a Timer in initState
  2. Update state every second
  3. Display the seconds in the build method
  4. Cancel the Timer in dispose

Here's an example:

class ClockWidget extends StatefulWidget {
  @override
  ClockWidgetState createState() => ClockWidgetState();
}

class ClockWidgetState extends State<ClockWidget> {
  Timer _timer;
  int _secondCount = 0;

  @override
  void initState() {
    super.initState();
    _timer = Timer.periodic(Duration(seconds: 1), (timer) {
      setState(() {
        this._secondCount += 1;
      });
    });
  }

  Widget build(BuildContext context) {
    print("${_secondCount}");
    return Text(
      "${_secondCount}",
      style: TextStyle(fontSize: 75, color: Color.fromRGBO(30, 144, 255, 1)),
    );
  }

  @override
  void dispose() {
    _timer.cancel();
    super.dispose();
  }
}