Я хочу разработать кнопку выхода, которая отправит меня в маршрут входа и удалит все остальные маршруты из Navigator
. Документация, похоже, не объясняет, как создать RoutePredicate
или иметь какую-либо функцию removeAll.
Я хочу разработать кнопку выхода, которая отправит меня в маршрут входа и удалит все остальные маршруты из Navigator
. Документация, похоже, не объясняет, как создать RoutePredicate
или иметь какую-либо функцию removeAll.
Ответы:
Я смог сделать это с помощью следующего кода:
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 .
Другое решение - использовать 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, это вам очень поможет.
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());
}
Не уверен, правильно ли я делаю
но это подходит для моего случая использования, пока не будет виджет root
void popUntilRoot({Object result}) {
if (Navigator.of(context).canPop()) {
pop();
popUntilRoot();
}
}