Skip to content

[Flutter] Use Timer Module to implement the countdown timer

If you want to countdown in Flutter, we can use Timer module to do it.


How to use Timer

First, we need to use Duration to determine how long we call the Timer.

var period = const Duration(seconds: 1);



Like this, we will call it every second. If you change the seconds to 5, we will call it every 5 seconds.


Timer.periodic(period, (timer) {
  // TODO

  setState(() {});
  });
}



Then we can use Timer in this way: calling the instructions we wrote down at regular intervals. And don't forget to set the end condition, otherwise the event will continue forever.


Sample

Let's take a look for sample code:

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

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

class MyApp extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: timerPage(),
    );
  }
}

class timerPage extends StatefulWidget {
  @override
  _timerPage createState() => _timerPage();
}

class _timerPage extends State<timerPage> {
  int time01 = 60;
  int time02 = 60;
  bool time01_start = false;
  bool time02_start = false;

  var period = const Duration(seconds: 1);

  void time01_button_event(){
    if (time01_start){
      time01_start = false;
    }
    else{
      time01_start = true;
    }

    Timer.periodic(period, (timer) {
      if (time01 < 1 || time01_start == false) {
        timer.cancel();
        timer = null;
      }
      else{
        time01--;
      }
      setState(() {});
    });
  }

  void time02_button_event(){
    if (time02_start){
      time02_start = false;
    }
    else{
      time02_start = true;
    }

    Timer.periodic(period, (timer) {
      if (time02 < 1 || time02_start == false) {
        timer.cancel();
        timer = null;
      }
      else{
        time02--;
      }
      setState(() {});
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text('$time01', style: TextStyle(fontSize: 40)),
                  RaisedButton(
                    onPressed: () => time01_button_event(),
                    child: Text(time01_start?'PAUSE':'START'),
                  )
                ],
              ),
              Container(
                width: MediaQuery.of(context).size.width/5,
              ),
              Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text('$time02', style: TextStyle(fontSize: 40)),
                  RaisedButton(
                    onPressed: () => time02_button_event(),
                    child: Text(time02_start?'PAUSE':'START'),
                  )
                ],
              ),
            ],
          )
        )
    );
  }
}



Output:

The countdowns on both sides are processed asynchronously, which is quite convenient.


BUG

Of course, if you actually try it, you will find that as long as you click the button, the time will be quickly reduced: this is obviously not the function we want.

Tags:

Leave a Reply