I have a stateful widget of stopwatch and I am using that widget on multiple pages. I am starting stopwatch on load but I want to stop stopwatch on some condition from my parent widget but that is not working.
My Stop Watch Code
class StopWatch extends StatefulWidget {
start() => createState().start();
stop() => createState().stop();
@override
_StopWatchState createState() => _StopWatchState();
}
class _StopWatchState extends State<StopWatch> {
String timeToDisplay = '00:00:00';
Stopwatch swatch = Stopwatch();
final duration = const Duration(seconds: 1);
void startTimer() {
Timer(duration, keepRunning);
}
void keepRunning() {
if (swatch.isRunning) {
startTimer();
}
setState(() {
var hours = swatch.elapsed.inHours.toString().padLeft(2, "0");
var minutes = (swatch.elapsed.inMinutes % 60).toString().padLeft(2, "0");
var seconds = (swatch.elapsed.inSeconds % 60).toString().padLeft(2, "0");
timeToDisplay = hours + ':' + minutes + ':' + seconds;
});
}
void start() {
swatch.start();
startTimer();
}
void stop() {
swatch.stop();
}
void pause() {
}
@override
void initState() {
// TODO: implement initState
start();
super.initState();
}
@override
void setState(fn) {
if(mounted){
super.setState(fn);
}
}
@override
void dispose() {
// TODO: implement dispose
swatch.stop();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
child: Text(
timeToDisplay,
style: TextStyle(
fontSize: 50.0, fontWeight: FontWeight.bold),
),
);
}
}
Parent widget.
class RecordTrackScreen extends StatefulWidget {
static String id = 'record-track';
@override
_RecordTrackScreenState createState() => _RecordTrackScreenState();
}
class _RecordTrackScreenState extends State<RecordTrackScreen> {
stopTimer() {
if (condition is true) {
StopWatch().stop();
}
}
}
StopTimer is calling stop method if condition is satisfy but stopwatch is not stopping. I tried to stop stopwatch in StopWatch class just to cross check but that is working fine.
Dart Pad Url - https://dartpad.dev/70a97f62f6bf2d3c51e322c651566240
I am not sure what I am doing wrong. Please help.
This line of code can't stop the stop watch because it is stopping a new instance of StopWatch which is different from the StopWatch you have used.
StopWatch().stop();
Use a boolean to control the stop and start of the stopWatch
MyWidget change to stateful widget
bool isStop = false;
@override
Widget build(BuildContext context) {
return Column(children: [
StopWatch(isStop: isStop),
RaisedButton(
onPressed: () {
setState(() {
isStop = true;
});
},
child: Text('stop')),
RaisedButton(
onPressed: () {
setState(() {
isStop = false;
});
},
child: Text('start'))
]);
}
StopWatch:
class StopWatch extends StatefulWidget {
final bool isStop;
const StopWatch({Key key, this.isStop}) : super(key: key);
@override
_StopWatchState createState() => _StopWatchState();
}
class _StopWatchState extends State<StopWatch> {
//...some code
@override
void didUpdateWidget(StopWatch oldWidget) {
super.didUpdateWidget(oldWidget);
// Check isStop value is different from the previous state
// this function will trigger when every time this widget is build
if (oldWidget.isStop != widget.isStop) {
widget.isStop ? stop() : start();
}
}
Not suggest to call the Widget function in the parent Widget, since every time build, there will be a new instance of the Widget