0

In a State class, despite not calling setState() call, it is rebuilt with new items when the widget is returned from Navigator.pop(). How could this happen?

On my simplified code below, the ListView is rebuilt whenever I clicked a button and pop the pushed widget.

Is it because Navigator.push() disposes a current widget and the widget is re-rendered after Navigator.pop() ?

class _TestState extends State<Test> {
  List<int> initialList = [];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FlatButton(
        onPressed: () async {
          var nothing = await Navigator.of(context).push(
            MaterialPageRoute(builder: (_context) => PushedWidget()),
          );
          // the State is rebuilt without calling setState()
          initialList.add(1);
        },
        child: Text('test'),
      ),
      body: Container(
        child: ListView.builder(
          itemCount: initialList.length,
          itemBuilder: (context, idx) {
            return Text('${initialList[idx]}');
          },
        ),
      ),
    );
  }
}

class PushedWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(leading: IconButton(onPressed: () => _pop(context), icon: Icon(Icons.close))),
    );
  }
  void _pop(BuildContext context) {
    Navigator.of(context).pop('popped');
  }
}

I've read docs and codes of implementation. But I couldn't find the answer to this question.

wurikiji
  • 327
  • 3
  • 12

1 Answers1

1

Navigator maintains a stack-based history of child widgets. I am considering that you already know about the data structure Stack. Navigator.push and Navigator.push works same like Stack. When we navigate to another screen, we use the push methods and Navigator widget adds the new screen onto the top of the stack. Whereas, the pop methods would remove that screen from the stack.

Hussam
  • 1,606
  • 9
  • 20
  • Thanks for your answer. I wonder whether `push` will stack **cached (already rendered) widget** or just **type of widget** so re-render it. – wurikiji Jan 23 '19 at 19:03
  • maintainState controls whether the route's widgets and render objects are kept around or not. If you set it to false on a route, then when another route is pushed on top, the entire subtree is thrown away until that route is popped. – Hussam Jan 23 '19 at 19:05
  • I really appreciate it! Thanks a lotttttttttt! – wurikiji Jan 23 '19 at 19:08