Flutter удаляет все маршруты

98

Я хочу разработать кнопку выхода, которая отправит меня в маршрут входа и удалит все остальные маршруты из Navigator. Документация, похоже, не объясняет, как создать RoutePredicateили иметь какую-либо функцию removeAll.

chrislondon
источник

Ответы:

267

Я смог сделать это с помощью следующего кода:

Navigator.of(context)
    .pushNamedAndRemoveUntil('/login', (Route<dynamic> route) => false);

Секрет здесь в использовании RoutePredicate, который всегда возвращает false (Route<dynamic> route) => false. В этой ситуации он удаляет все маршруты, кроме нового /loginмаршрута, который я отправил.

chrislondon
источник
1
Большое спасибо, это сработало успешно. Не могли бы вы прислать ссылку, где я смогу понять больше ....
Паван
У меня проблема с этим! В iOS, используя собственное представление в качестве виджета, после использования вашего метода собственное представление не удаляется должным образом и продолжает существовать, в результате у меня есть представление, которое больше никогда не будет использоваться, работает в некотором роде в фоновом режиме и его невозможно удалить . Кажется, это происходит только на устройствах iOS.
Лоренцо Императрис
@LorenzoImperatrice Вы нашли решение этой проблемы? У меня аналогичная проблема
Матеуш
3
У меня все еще есть открытые экземпляры даже после этого. любое другое решение для нажатия экрана и удаления остальной части стека?
Manoj MM
Как мы можем передавать аргументы при таком подходе.
Developine
78

я могу сделать это с помощью следующего фрагмента кода:

 Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) =>
    LoginScreen()), (Route<dynamic> route) => false),

если вы хотите удалить весь маршрут ниже отправленного маршрута, RoutePredicate всегда возвращает false , например (Route route) => false .

амир хан
источник
24

Другая альтернатива - popUntil()

Navigator.of(context).popUntil(ModalRoute.withName('/root'));

Это отключит все маршруты, пока вы не вернетесь к названному маршруту.

Nleslie
источник
1
Я предпочитаю этот ответ!
ноябрь
10

Если вы хотите вернуться к конкретному экрану и не используете именованный маршрутизатор, можете использовать следующий подход.

Пример:

Navigator.pushAndRemoveUntil(context,
                  MaterialPageRoute(builder: (BuildContext context) => SingleShowPage()),
                  (Route<dynamic> route) => route is HomePage
              );

С помощью route is HomePage вы проверяете имя своего виджета.

Владимир Биловус
источник
что такое NoAnimatedRoute? Не удается найти класс с таким именем во Flutter
kashlo
@kashlo Не обращайте внимания =) Просто моя реализация может использовать вместо этого MaterialPageRoute. Но я отредактировал ответ, спасибо.
Владимир Биловус
(Route <dynamic> route) => route.isFirst) Если кто-то хочет удалить до первого маршрута.
Хусснайн Хайдар,
4

Если вы используете namedRoutes, вы можете сделать это просто:

Navigator.pushNamedAndRemoveUntil(context, "/login", (Route<dynamic> route) => false);

Где «/ login» - это маршрут, который вы хотите добавить в стек маршрутов.

Обратите внимание, что :

Этот оператор удаляет все маршруты в стеке и делает один из них корневым.

Кельвин Мбото
источник
3

Я не знаю, почему никто не упомянул решение с использованием SchedularBindingInstance , но немного поздно для вечеринки, я думаю, что это был бы правильный способ сделать это, первоначально ответили здесь

    SchedulerBinding.instance.addPostFrameCallback((_) async {
                              Navigator.of(context).pushNamedAndRemoveUntil(
                                  '/login',
                                  (Route<dynamic> route) => false);
                            });

Приведенный выше код удаляет все маршруты и навигационные теги в '/ login', это также гарантирует, что все кадры отображаются перед переходом к новому маршруту путем планирования обратного вызова

maheshmnj
источник
1

Это работает для меня. На самом деле я работал с блоком, но моей проблемой был блок экрана входа в систему. После выхода из системы он не обновлялся. Он содержал данные предыдущей модели. Даже, я ввел неправильную запись. Это был главный экран.

Шаг 1:

Navigator.of(context).pushNamedAndRemoveUntil(
        UIData.initialRoute, (Route<dynamic> route) => false);

где, UIData.initialRoute = "/" or "/login"

Шаг 2:

Работает над обновлением экрана. Если вы работаете с Bloc, это вам очень поможет.

runApp(MyApp());

где, MyApp() is the root class.

Код корневого класса (т.е. MyApp)

class MyApp extends StatelessWidget {

  final materialApp = Provider(
      child: MaterialApp(
          title: UIData.appName,
          theme: ThemeData(accentColor: UIColor().getAppbarColor(),
            fontFamily: UIData.quickFont,
          ),
          debugShowCheckedModeBanner: false,
          //home: SplashScreen(),
          initialRoute: UIData.initialRoute,
          routes: {
            UIData.initialRoute: (context) => SplashScreen(),
            UIData.loginRoute: (context) => LoginScreen(),
            UIData.homeRoute: (context) => HomeScreen(),
          },
          onUnknownRoute: (RouteSettings rs) => new MaterialPageRoute(
              builder: (context) => new NotFoundPage(
                appTitle: UIData.coming_soon,
                icon: FontAwesomeIcons.solidSmile,
                title: UIData.coming_soon,
                message: "Under Development",
                iconColor: Colors.green,
              )
          )));

  @override
  Widget build(BuildContext context) {
    return materialApp;
  }
}

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

Вот мой метод выхода ,

void logout() async {
    SharedPreferences preferences = await SharedPreferences.getInstance();
    preferences.clear();

    // TODO: we can use UIData.loginRoute instead of UIData.initialRoute
    Navigator.of(context).pushNamedAndRemoveUntil(
        UIData.initialRoute, (Route<dynamic> route) => false);
    //TODO: It's working as refresh the screen
    runApp(MyApp());
  }
рокзвезда
источник
0

Не уверен, правильно ли я делаю

но это подходит для моего случая использования, пока не будет виджет root

void popUntilRoot({Object result}) {
    if (Navigator.of(context).canPop()) {
      pop();
      popUntilRoot();
    }
}
Винеш Раджу
источник
0
to clear route - 

  onTap: () {
                    //todo to clear route -
                    Navigator.of(context).pop();
                    Navigator.push(context, MaterialPageRoute(builder: (context) => UpdateEmployeeUpdateDateActivity(_token),));
                    widget.listener.onEmployeeDateClick(_day,_month, _year);
}
sj
источник