How can I call setState() safely after returning a value from a dialog in Flutter?

Issue

Here is the problem: I have a list of items displayed in a list view. I can edit these items with the dialogs displayed by clicking on them. After editing and closing the dialog, I also need to update the items on the list view. I’m currently doing this with the following code snippet in my list view item widget:

showDialog(
  context: context,
  builder: (context) {
    return UpdateItemDialog(item: _item);
  },
).then((updatedItem) {
  if (updatedItem != null) {
    setState(() => _item = updatedItem);
  }
});

and by calling Navigator.of(context).pop(_item); from my dialog.

It works perfectly fine when there are no rebuilds occur until the dialog is dismissed. However, for example, if the orientation is changed when the dialog is open, I get Unhandled Exception: setState() called after dispose() error since the list view also rebuilt because of the orientation change and the then clause in my code runs on the destroyed widget.

Is there a way to access the rebuilt widget from a destroyed widget?

Or should I use a different approach to this problem?

By the way, changes should only be accepted after the dialog is dismissed, so I should return the item from the dialog.

Solution

I believe your best bet would be to introduce even a simple state management solution (Provider would be good) to handle communication between a dialog and other widgets.

Check out the Gist below (Run it on Dartpad.dev) as an example how you can keep it simple, yet clean and decoupled
https://gist.github.com/romanejaquez/8aed8d699fba8fdfff4b0966dfe47663

in which I show that instead of passing data from a dialog back to another widget, a State Management solution would allow you for a decoupled way of passing data back and forth, notifying each other and triggering rebuilds (which is kind of calling setState() since pretty much that’s what you want – trigger a rebuild on the other widget. In this example, I’m sending a value back to the originating widget and triggering a rebuild (thanks to the Consumer widget listening to the changes triggered in the common service. That’d be my honest suggestion.

Answered By – Roman Jaquez

Answer Checked By – Jay B. (FlutterFixes Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *