Я хочу разработать кнопку выхода, которая отправит меня в маршрут входа и удалит все остальные маршруты из Navigator
. Документация, похоже, не объясняет, как создать RoutePredicate
или иметь какую-либо функцию removeAll.
98
Я смог сделать это с помощью следующего кода:
Navigator.of(context)
.pushNamedAndRemoveUntil('/login', (Route<dynamic> route) => false);
Секрет здесь в использовании RoutePredicate, который всегда возвращает false (Route<dynamic> route) => false
. В этой ситуации он удаляет все маршруты, кроме нового /login
маршрута, который я отправил.
я могу сделать это с помощью следующего фрагмента кода:
Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => LoginScreen()), (Route<dynamic> route) => false),
если вы хотите удалить весь маршрут ниже отправленного маршрута, RoutePredicate всегда возвращает false , например (Route route) => false .
источник
Другая альтернатива -
popUntil()
Navigator.of(context).popUntil(ModalRoute.withName('/root'));
Это отключит все маршруты, пока вы не вернетесь к названному маршруту.
источник
Другое решение - использовать
pushAndRemoveUnit()
. Чтобы удалить все остальные маршруты, используйтеModalRoute.withName('/')
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (BuildContext context) => Login()), ModalRoute.withName('/'));
Ссылка: https://api.flutter.dev/flutter/widgets/NavigatorState/pushAndRemoveUntil.html
источник
Если вы хотите вернуться к конкретному экрану и не используете именованный маршрутизатор, можете использовать следующий подход.
Пример:
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (BuildContext context) => SingleShowPage()), (Route<dynamic> route) => route is HomePage );
С помощью route is HomePage вы проверяете имя своего виджета.
источник
Если вы используете namedRoutes, вы можете сделать это просто:
Navigator.pushNamedAndRemoveUntil(context, "/login", (Route<dynamic> route) => false);
Где «/ login» - это маршрут, который вы хотите добавить в стек маршрутов.
Обратите внимание, что :
источник
Я не знаю, почему никто не упомянул решение с использованием SchedularBindingInstance , но немного поздно для вечеринки, я думаю, что это был бы правильный способ сделать это, первоначально ответили здесь
SchedulerBinding.instance.addPostFrameCallback((_) async { Navigator.of(context).pushNamedAndRemoveUntil( '/login', (Route<dynamic> route) => false); });
Приведенный выше код удаляет все маршруты и навигационные теги в '/ login', это также гарантирует, что все кадры отображаются перед переходом к новому маршруту путем планирования обратного вызова
источник
Это работает для меня. На самом деле я работал с блоком, но моей проблемой был блок экрана входа в систему. После выхода из системы он не обновлялся. Он содержал данные предыдущей модели. Даже, я ввел неправильную запись. Это был главный экран.
Шаг 1:
Navigator.of(context).pushNamedAndRemoveUntil( UIData.initialRoute, (Route<dynamic> route) => false);
где,
UIData.initialRoute = "/" or "/login"
Шаг 2:
Работает над обновлением экрана. Если вы работаете с Bloc, это вам очень поможет.
где,
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()); }
источник
Не уверен, правильно ли я делаю
но это подходит для моего случая использования, пока не будет виджет root
void popUntilRoot({Object result}) { if (Navigator.of(context).canPop()) { pop(); popUntilRoot(); } }
источник
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); }
источник