How can I completely dispose the function/screen?
Below the reproduce code, after I press navigator pop to the home screen, I expected the next screen is popped and all function is stopped, but the function in the while keeps running.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class Config {
static int count = 0;
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const HomeScreen(),
);
}
}
class NextScreen extends StatefulWidget {
const NextScreen({super.key});
@override
State<NextScreen> createState() => _NextScreenState();
}
class _NextScreenState extends State<NextScreen> with WidgetsBindingObserver {
int timerCount = 0;
bool status = false;
bool isCurrentStatus = true;
@override
void initState() {
super.initState();
getInit();
}
void getInit() {
try {
WidgetsBinding.instance.addPostFrameCallback((_) async {
startLoopStatus();
});
} catch (e) {
print('[getInit] ERROR:: $e');
}
}
Future<void> startLoopStatus() async {
print('[startLoopStatus] Running startLoopStatus 001.');
print(isCurrentStatus);
while (status == false && isCurrentStatus) {
if (mounted) {
Future.delayed(Duration.zero, () {
setState(() {
timerCount += 1;
});
});
}
await Future.delayed(const Duration(seconds: 2), () {
debugPrint("delay----------");
Config.count += 1;
print(Config.count);
});
await loopArrive();
}
}
Future<void> loopArrive() async {
print('[loopArrive] Running loopArrive 001.');
print('[loopArrive] timerCount: $timerCount');
try {
if (mounted) {
if (ModalRoute.of(context)!.isCurrent) {
print('[loopArrive] Running loopArrive 002.');
}
}
} catch (e) {
print('[loopArrive] ERROR:: $e');
}
}
@override
void dispose() {
print('[NextScreen] dispose()');
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Next'),
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
Navigator.of(context).pop();
},
),
),
body: const SafeArea(
child: Center(
child: Column(
children: [
Text('Please see the terminal output.'),
],
),
),
),
);
}
}
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home'),
),
body: SafeArea(
child: Center(
child: Column(
children: [
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => const NextScreen()),
);
},
child: const Text('Go to next page'),
),
],
),
),
),
);
}
}
2
Answers
The second screen’s state continues to exist even when you navigate to the home screen. If your method that displays messages is running periodically using something like a Timer or Future.delayed, it will continue running until explicitly stopped.
To ensure that the method stops when you navigate away from the second screen, you can use the dispose method of the StatefulWidget.
So you can add a Timer to cancel with the dispose call.
But also with that the :
will continue to work !! so you can add a
Completer<void>
to finish the block..the full code :
Just put a variable to stop the loop here :