Flutter Navigator 2.0 什么时候 route.didPop(result) 等于 false

When does route.didPop(result) is equal to false in Flutter Navigator 2.0

Flutter Navigator 2.0 的主要机制之一是 RouterDelegate > build > Navigator 中的 onPopPage 函数。但是,我不明白什么时候 route.didPop(result) returns false.

我们可以使用John Ryan's famous example to show my question. His demo code.

onPopPage: (route, result) {
  if (!route.didPop(result)) {
    return false;
  }

  // Update the list of pages by setting _selectedBook to null
  _selectedBook = null;
  show404 = false;
  notifyListeners();

  return true;
},

在我的所有测试中,使用 AppBar 自动生成的后退按钮,route.didPop(结果)return是正确的。

文档保持:

bool didPop(dynamic result)
package:flutter/src/widgets/navigator.dart

A request was made to pop this route. If the route can handle it internally (e.g. because it has its own stack of internal state) then return false, otherwise return true (by returning the value of calling super.didPop). Returning false will prevent the default behavior of [NavigatorState.pop].

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.

This method should call [didComplete] to resolve the [popped] future (and this is all that the default implementation does); routes should not wait for their exit animation to complete before doing so.

See [popped], [didComplete], and [currentResult] for a discussion of the result argument.

但是“如果路由可以在内部处理它(例如,因为它有自己的内部状态堆栈)那么 return false”是什么意思?路线有自己的内部状态堆栈?如何产生这个结果?

谢谢,注意安全

经过一些研究以完全理解 Navigator 2.0,我认为这可能是问题的答案: route.didPop(result) 将 return false,当被要求弹出的路由保留本地历史条目并且必须在弹出完整路由之前删除它们。

那么什么是本地历史条目(内部状态堆栈)?

本地历史条目是一种在页面内实现本地导航的方式。您可以使用方法 addLocalHistoryEntry 来完成此操作。为了更好地理解这一点,请查看官方 Flutter Docs 示例:

The following example is an app with 2 pages: HomePage and SecondPage. The HomePage can navigate to the SecondPage. The SecondPage uses a LocalHistoryEntry to implement local navigation within that page. Pressing 'show rectangle' displays a red rectangle and adds a local history entry. At that point, pressing the '< back' button pops the latest route, which is the local history entry, and the red rectangle disappears. Pressing the '< back' button a second time once again pops the latest route, which is the SecondPage, itself. Therefore, the second press navigates back to the HomePage.

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: '/',
      routes: {
        '/': (BuildContext context) => HomePage(),
        '/second_page': (BuildContext context) => SecondPage(),
      },
    );
  }
}

class HomePage extends StatefulWidget {
  HomePage();

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Text('HomePage'),
            // Press this button to open the SecondPage.
            ElevatedButton(
              child: Text('Second Page >'),
              onPressed: () {
                Navigator.pushNamed(context, '/second_page');
              },
            ),
          ],
        ),
      ),
    );
  }
}

class SecondPage extends StatefulWidget {
  @override
  _SecondPageState createState() => _SecondPageState();
}

class _SecondPageState extends State<SecondPage> {

  bool _showRectangle = false;

  void _navigateLocallyToShowRectangle() async {
    // This local history entry essentially represents the display of the red
    // rectangle. When this local history entry is removed, we hide the red
    // rectangle.
    setState(() => _showRectangle = true);
    ModalRoute.of(context).addLocalHistoryEntry(
        LocalHistoryEntry(
            onRemove: () {
              // Hide the red rectangle.
              setState(() => _showRectangle = false);
            }
        )
    );
  }

  @override
  Widget build(BuildContext context) {
    final localNavContent = _showRectangle
      ? Container(
          width: 100.0,
          height: 100.0,
          color: Colors.red,
        )
      : ElevatedButton(
          child: Text('Show Rectangle'),
          onPressed: _navigateLocallyToShowRectangle,
        );

    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            localNavContent,
            ElevatedButton(
              child: Text('< Back'),
              onPressed: () {
                // Pop a route. If this is pressed while the red rectangle is
                // visible then it will will pop our local history entry, which
                // will hide the red rectangle. Otherwise, the SecondPage will
                // navigate back to the HomePage.
                Navigator.of(context).pop();
              },
            ),
          ],
        ),
      ),
    );
  }
}

要查看文档中的示例,请单击 here

我希望我以一种可以理解的方式回答了这个问题。