I call showDialog to construct an AlertDialog that receives TextEditingController. I await for the dialog to close, and then I try to dispose the controller. But I get an exception:
A TextEditingController was used after being disposed.
Why is this happening? And how do I wait until the dialog is destroyed for sure?
My code:
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () => _onPressed(context),
child: Text('Show'),
),
),
);
}
void _onPressed(BuildContext context) async {
final controller = TextEditingController();
await showDialog(
context: context,
builder: (_) => MyDialog(controller),
);
controller.dispose();
}
}
class MyDialog extends StatelessWidget {
final TextEditingController controller;
MyDialog(this.controller);
@override
Widget build(BuildContext context) {
return AlertDialog(
content: TextField(
controller: controller,
),
);
}
}
My next attempt was to wrap dispose() into this:
SchedulerBinding.instance!.addPostFrameCallback((_) {
controller.dispose();
});
Still the error persists.
This error is not visible to the user and could be ignored. Also the controller is not that expensive to leave undisposed. Finally I can use StatefulWidget for the dialog content, create the controller there and dispose it in the widget's dispose().
But I am mostly interested in the framework design that leads to this as my case is actually more elaborate.
So why is this happening? And how do I wait until the dialog is destroyed for sure?