I want to stop the timer when I navigate to another page.
The following is my code
//imports
late Timer timer;
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var selectedIndex = 0;
@override
Widget build(BuildContext context) {
Widget page;
switch (selectedIndex) {
case 0:
page = const MonitorPage();
case 1:
page = const ReportPage();
case 2:
page = const Placeholder();
default:
throw UnimplementedError("not found");
}
return LayoutBuilder(builder: (context, constraints) {
return Scaffold(
body: Row(
children: [
SafeArea(
child: NavigationRail(
extended: constraints.maxWidth >= 600,
destinations: const [
NavigationRailDestination(
icon: Icon(Icons.home),
label: Text('main'),
),
NavigationRailDestination(
icon: Icon(Icons.list),
label: Text('report'),
),
NavigationRailDestination(
icon: Icon(Icons.settings),
label: Text("setting"),
),
],
selectedIndex: selectedIndex,
onDestinationSelected: (value) {
setState(() {
if (selectedIndex == 0) {
timer.cancel(); // here I'd like to cancel the timer
}
selectedIndex = value;
});
},
),
),
Expanded(
child: Container(
color: Theme.of(context).colorScheme.primaryContainer,
child: page,
),
)
],
),
);
});
}
}
class _MonitorPageState extends State<MonitorPage> {
late String _time;
@override
void initState() {
_time =
"${DateTime.now().year.toString().padLeft(4, '0')}-${DateTime.now().month.toString().padLeft(2, '0')}-${DateTime.now().day.toString().padLeft(2, '0')} ${DateTime.now().hour.toString().padLeft(2, '0')}:${DateTime.now().minute.toString().padLeft(2, '0')}:${DateTime.now().second.toString().padLeft(2, '0')}";
timer = Timer.periodic(const Duration(seconds: 1), (timer) { // here i set the timer variable
_updateTime(); //just updating time
});
super.initState();
}
@override
Widget build(BuildContext context) {
...
}
}
I was expecting to cancel the timer, but it gave me this message.
======== Exception caught by gesture ===============================================================
The following LateError was thrown while handling a gesture:
LateInitializationError: Field 'timer' has not been initialized.
When the exception was thrown, this was the stack:
#0 timer (package:TPSEM_pocket/main.dart)
#1 _MyHomePageState.build.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:TPSEM_pocket/main.dart:184:23)
#2 State.setState (package:flutter/src/widgets/framework.dart:1203:30)
#3 _MyHomePageState.build.<anonymous closure>.<anonymous closure> (package:TPSEM_pocket/main.dart:182:19)
#4 _NavigationRailState.build.<anonymous closure> (package:flutter/src/material/navigation_rail.dart:463:62)
#5 _InkResponseState.handleTap (package:flutter/src/material/ink_well.dart:1183:21)
#6 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:315:24)
#7 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:652:11)
#8 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:309:5)
#9 BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:242:7)
#10 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:670:9)
#11 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:98:12)
#12 PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:143:9)
#13 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:633:13)
#14 PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:141:18)
#15 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:127:7)
#16 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:495:19)
#17 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:475:22)
#18 RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:430:11)
#19 GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:420:7)
#20 GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:383:5)
#21 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:330:7)
#22 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:299:9)
#23 _invoke1 (dart:ui/hooks.dart:328:13)
#24 PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:429:7)
#25 _dispatchPointerDataPacket (dart:ui/hooks.dart:262:31)
Handler: "onTap"
Recognizer: TapGestureRecognizer#0c5e3
debugOwner: GestureDetector
state: possible
won arena
finalPosition: Offset(115.5, 71.5)
finalLocalPosition: Offset(115.5, 19.5)
button: 1
sent tap down
====================================================================================================
this is the point => LateInitializationError: Field 'timer' has not been initialized.
I tried to use a state variable and set it to timer then cancel it in onDestinationSelected
(right before changing the selectedIndex
variable), butt it didn’t work either.
How could I fix it? Thanks.
3
Answers
Define the
timer
variable inside the_MyHomePageState
class. That will be accessible within the state class and can be canceled.Additionally, cancel the
timer
in thedispose()
method to avoid memory leaks & it will stop or cancel thetimer
.Here is the updated code:
In this case you can dispose your timer variable in dispose method like this.
Try the below code to access the timer, pass the reference object to the Monitor page can use the state management approach for accessing the timer across the pages.