Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
331 views
in Technique[技术] by (71.8m points)

In Flutter Navigator 2, what didPop is really doing?

Minimal reproducible code:

void main() => runApp(FooApp());

class FooApp extends StatefulWidget {
  @override
  _FooAppState createState() => _FooAppState();
}

class _FooAppState extends State<FooApp> {
  bool _showPage2 = false;
  void _onPressed(bool value) => setState(() => _showPage2 = value);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Navigator(
        onPopPage: (route, result) => route.didPop(result),
        pages: [
          MaterialPage(child: Page1(onPressed: _onPressed)),
          if (_showPage2) MaterialPage(child: Page2()),
        ],
      ),
    );
  }
}

class Page1 extends StatelessWidget {
  final ValueChanged<bool> onPressed;
  const Page1({Key key, this.onPressed}) : super(key: key);

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Page1')),
      body: ElevatedButton(
        onPressed: () => onPressed(true),
        child: Text('Page2'),
      ),
    );
  }
}

class Page2 extends StatefulWidget {
  @override
  _Page2State createState() => _Page2State();
}

class _Page2State extends State<Page2> {
  void dispose() {
    super.dispose();
    print('dispose'); 
  }

  Widget build(BuildContext context) => Scaffold(appBar: AppBar(title: Text('Page2')));
}

didPop:

When this function returns true, the navigator removes this route from the history but does not yet call dispose. Instead, it is the route's responsibility to call NavigatorState.finalizeRoute, which will in turn call dispose on the route. This sequence lets the route perform an exit animation (or some other visual effect) after being popped but prior to being disposed.

But in my example, you can see without having to call NavigatorState.finalizeRoute in Page2, dispose method does get called contradiciting Docs.

question from:https://stackoverflow.com/questions/66051297/in-flutter-navigator-2-what-didpop-is-really-doing

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's done internally when using MaterialPage/_PageBasedMaterialPageRoute. You can poke around in the code starting in the Navigator class, which appears to lead up to this OverlayRoute class. If you do want to trace through yourself, it wasn't a walk in the park for me and you'll have to pay close attention to how each class is related.

This class has the finishedWhenPopped getter, which is true by default. And if you look at the didPop override implementation right below the getter definition, didPop will internally call finalizeRoute when finishedWhenPopped is true.

Implementation from OverlayRoute class

@protected
bool get finishedWhenPopped => true;

@override
bool didPop(T? result) {
  final bool returnValue = super.didPop(result);
  assert(returnValue);
  if (finishedWhenPopped)
    navigator!.finalizeRoute(this);
  return returnValue;
}

This is true only for at least MaterialPage/_PageBasedMaterialPageRoute. Other implementations don't necessarily do this.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...