Метушня видаляє всі маршрути


98

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

Відповіді:


267

Я зміг досягти цього за допомогою такого коду:

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

Секрет тут полягає у використанні RoutePredicate, який завжди повертає false (Route<dynamic> route) => false. У цій ситуації він видаляє всі маршрути, крім нового /loginмаршруту, який я просунув.


1
Велике спасибі це вдало працювало. Не могли б ви надіслати якесь посилання, де я зможу більше зрозуміти ....
Паван

У мене проблема з цим! У iOS, використовуючи власний вигляд як віджет, після використання вашого методу власний вигляд не розпоряджається належним чином і продовжує існувати, в результаті у мене є подання, яке ніколи більше не використовуватиметься, виконуючись у певному фоні і неможливе розпорядження . Здається, це відбувається лише на пристроях iOS.
Lorenzo Imperatrice

@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'));

Це призведе до вимкнення всіх маршрутів, поки ви не повернетесь до вказаного маршруту.


1
Я віддаю перевагу цій відповіді!
листопад


10

Якщо ви хочете повернутися до певного екрану, і ви не використовуєте іменований маршрутизатор, можна скористатися наступним підходом

Приклад:

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

Якщо маршрут є HomePage, ви перевіряєте назву свого віджета.


що таке NoAnimatedRoute? Не
можу

@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', це також робить впевненим, що всі кадри відображаються перед переходом на новий маршрут, плануючи зворотний виклик


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());

Ось метод My Logout ,

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);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.