Когда route.didPop (result) равен false в Flutter Navigator 2.0

Один из основных механизмов Flutter Navigator 2.0 - это функция onPopPage внутри RouterDelegate ›build› Navigator. Однако я не понимаю, когда route.didPop (result) возвращает false.

Мы можем использовать знаменитый пример Джона Райана, чтобы покажи мой вопрос. Его демонстрационный код.

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 (result) возвращает true.

Документ остается:

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.

Но разве если маршрут может обрабатывать его внутренне (например, потому что у него свой собственный стек внутреннего состояния), то возвращать ложное среднее? У маршрута есть свой стек внутреннего состояния? Как добиться такого результата?

Спасибо, оставайся в безопасности


person Dimitri Leurs    schedule 10.11.2020    source источник


Ответы (1)


После некоторого исследования, чтобы полностью понять Navigator 2.0, я думаю, что это может быть ответ на вопрос: route.didPop (result) вернет false, когда Route, который запрашивают всплытие, сохраняет записи локальной истории, и они должны быть удалены, прежде чем появится полный маршрут.

Так что же такое записи локальной истории (стек внутренних состояний)?

Записи локальной истории - это способ реализовать локальную навигацию на странице. Вы можете сделать это с помощью метода addLocalHistoryEntry. Чтобы лучше понять это, взгляните на официальный образец Flutter Docs:

В следующем примере показано приложение с двумя страницами: HomePage и SecondPage. Домашняя страница может перейти на вторую страницу. SecondPage использует LocalHistoryEntry для реализации локальной навигации на этой странице. Нажатие кнопки «Показать прямоугольник» отображает красный прямоугольник и добавляет запись локальной истории. В этот момент нажатие кнопки «‹ назад »отображает последний маршрут, который является записью локальной истории, и красный прямоугольник исчезает. При повторном нажатии кнопки «‹ назад »снова появляется последний маршрут, которым является сама SecondPage. Таким образом, второе нажатие возвращает на домашнюю страницу.

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();
              },
            ),
          ],
        ),
      ),
    );
  }
}

Чтобы просмотреть образец в документации, щелкните здесь / а>.

Надеюсь, я ответил на вопрос понятно.

person Nico    schedule 20.01.2021