Fluter Countdown Timer

352

When you pop back, any "state" in the widget will be destroyed.

There are three kinds of method you can do to prevent "state" being destroyed (or memory release):

  • Using static property
  • Using state manager by Provider
  • Using state manager by static instance

There are still many method to manage your state, but not mention here, see details in this repo

Static property

Static property is something like variable outside your class, like:

// prefix "_" for private variable
String _myStaticVar = 'hello world';

class MyWidget {}

Rather, it is class based variable. Which means it can help you describe the variable more. like class Dog can has a static property static final footShouldHave = 4. Class based programing is popular because it can manage your state and any logic action "inside" the class, and make it easier to understand and code.

When the class is being destroyed (memory release), any "state" inside the class should be pop from stack but not static. You can see more detail by knowing how compiler works.

In your case, you can do something like:

class MyTimer extends StatlessWidget {
  static DateTime? starter;

  Widget build(context) {
    if (starter == null) {
      starter = DateTime.now();
    }
    final secondPass = (DateTime.now().millisecondsSinceEpoch - starter!.millisecondsSinceEpoch) / 1000;
    final secondLeft = 60 - secondPass;
    return Text(secondLeft.toString());
  }
}

Provide state manager by Provider

Provider is made for flutter and also maintained by flutter team. It can make you easy to manage any class by accessing it from context.

It have many features, including use ChangeNotifier's model to "notify" widget that it is the time to reload your page!

You can also set up how the manager create.

  • lazy, create only when you need it
  • create in future
  • ...

In your case, it should be like:

  1. Build your helper class TimerManager
  2. Bind with Provider
  3. Get it from your context. Now when your widget is released, it still be existed in parent context (if their do exist a parent).

Build your helper class TimerManager

class TimerManager {
  final DateTime? starter;

  void startIfNeed() {
    if (starter != null) {
      starter = DateTime.now();
    }
  }

  num get secondLeft => 60 - (DateTime.now().millisecondsSinceEpoch - starter!.millisecondsSinceEpoch) / 1000
}

Bind with Provider

void main() {
  runApp(MaterialApp(
    home: Provider<TimerManager>(
      create: () => TimerManager(),
      child: Homepage(),
    )
  ));
}

Your parent widget

class Homepage extends statelessWidget {
  Widget build(context) {
    return TextButton(
      onPressed: () => navigateToTimer(context),
      child: Text('go'),
    );
  }

  void navigateToTimer(Build context) {
    Navigator.of(context).push(
      MaterialPageRoute(builder: (_) => MyTimer()),
    );
  } 
}

Your timer widget

// remember to import provider to able `context.read()`.
// see more detail on document.
import 'package:provider/provider.dart';

class MyTimer extends StatlessWidget {
  Widget build(context) {
    final manager = context.read<TimerManager >();
    manager.startIfNeed();

    return Text(manager.secondLeft.toString());
  }
}

static instance

Kind of combined method from 1 and 2.

class TimerManager {
  // make it singleton
  static final TimerManager  instance = TimerManager._();

  // It is now private constructor
  const TimerManager._();

  ...
}

Just call it in your widget

class MyTimer extends StatlessWidget {
  Widget build(context) {
    TimerManager.instance.startIfNeed();

    return Text(TimerManager.instance.secondLeft.toString());
  }
}

Summary

There is no best way to keep your state in generally, but in your case, I recommend Provider method.

Seems like you are looking for the answer that code is exactly fit in your case, which is not a good thing. It will miss the chance to figure it out by yourself and the joy of coding.

Share:
352
ARPIT JAISWAL IET Student
Author by

ARPIT JAISWAL IET Student

Updated on November 23, 2022

Comments

  • ARPIT JAISWAL IET Student
    ARPIT JAISWAL IET Student over 1 year

    I am trying to create a timer app which have multiple countdown timer for different task. Issue, I am facing is that, if I start one timer, and press back button, timer stops. So I want, that timer to run till either it is being paused or timer ends and alerts the user or app is destroyed. Help me how can I do this using Flutter? Any Sample Code Will be Appreciated? Solution will be rewarded

    enter link description here

    CountDownController _controller = CountDownController();
    
    CircularCountDownTimer(
                    width: MediaQuery.of(context).size.width / 6,
                    height: MediaQuery.of(context).size.width / 6,
                    duration: 120,
                    fillColor: Colors.green,
                    ringColor: Colors.white,
                    controller: _controller,
                    backgroundColor: Colors.white54,
                    strokeWidth: 10.0,
                    strokeCap: StrokeCap.round,
                    isTimerTextShown: true,
                    isReverse: false,
                    onComplete: () {
                      Notify();
                    },
                    textStyle: TextStyle(fontSize: 20.0, color: 
          Colors.black),
                  ),