Fluter Countdown Timer
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:
- Build your helper class
TimerManager
- Bind with
Provider
- Get it from your
context
. Now when your widget is released, it still be existed in parentcontext
(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.
ARPIT JAISWAL IET Student
Updated on November 23, 2022Comments
-
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
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), ),