Quero desenvolver um botão de logout que me encaminhe para a rota de login e remova todas as outras rotas do Navigator
. A documentação não parece explicar como fazer RoutePredicate
ou ter qualquer tipo de função removeAll.
107
Consegui fazer isso com o seguinte código:
Navigator.of(context)
.pushNamedAndRemoveUntil('/login', (Route<dynamic> route) => false);
O segredo aqui é usar um RoutePredicate que sempre retorna falso (Route<dynamic> route) => false
. Nessa situação, ele remove todas as rotas, exceto a nova /login
rota que empurrei.
posso fazer com o seguinte snippet de código:
Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => LoginScreen()), (Route<dynamic> route) => false),
se você quiser remover toda a rota abaixo da rota empurrada, RoutePredicate sempre retorna falso , por exemplo (rota de rota) => falso .
fonte
Outra alternativa é
popUntil()
Navigator.of(context).popUntil(ModalRoute.withName('/root'));
Isso removerá todas as rotas até que você retorne à rota nomeada.
fonte
Outra solução é usar
pushAndRemoveUntil()
. Para remover todas as outras rotas, useModalRoute.withName('/')
Navigator.pushAndRemoveUntil( context, MaterialPageRoute(builder: (BuildContext context) => Login()), ModalRoute.withName('/') );
Referência: https://api.flutter.dev/flutter/widgets/NavigatorState/pushAndRemoveUntil.html
fonte
Caso você queira voltar para a tela específica e não use o roteador nomeado, pode usar a próxima abordagem
Exemplo:
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (BuildContext context) => SingleShowPage()), (Route<dynamic> route) => route is HomePage );
Com o route is HomePage você verifica o nome do seu widget.
fonte
Se estiver usando namedRoutes, você pode fazer isso simplesmente:
Navigator.pushNamedAndRemoveUntil(context, "/login", (Route<dynamic> route) => false);
Onde "/ login" é a rota que você deseja empurrar na pilha de rotas.
Observe que :
fonte
Não sei por que ninguém mencionou a solução usando SchedularBindingInstance , um pouco tarde para a festa, porém, acho que essa seria a maneira certa de fazê-lo originalmente respondido aqui
SchedulerBinding.instance.addPostFrameCallback((_) async { Navigator.of(context).pushNamedAndRemoveUntil( '/login', (Route<dynamic> route) => false); });
O código acima remove todas as rotas e naviagtes para '/ login' isto também garante que todos os frames são renderizados antes de navegar para a nova rota agendando um retorno de chamada
fonte
Isso está funcionando para mim. Na verdade, eu estava trabalhando com o bloco mas meu problema era o bloco da tela de login. Não foi atualizado após o logout. Ele estava mantendo os dados do modelo anterior. Mesmo, eu digitei a entrada errada Ele estava indo para a tela inicial.
Passo 1:
Navigator.of(context).pushNamedAndRemoveUntil( UIData.initialRoute, (Route<dynamic> route) => false);
Onde,
UIData.initialRoute = "/" or "/login"
Passo 2:
Ele está trabalhando para atualizar a tela. Se você estiver trabalhando com o Bloc, será muito útil.
Onde,
MyApp() is the root class.
Código da classe raiz (ou seja, 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());
Aqui está o método 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()); }
fonte
Não tenho certeza se estou fazendo isso direito
mas isso se adequa ao meu caso de uso de pop-up até por widget raiz
void popUntilRoot({Object result}) { if (Navigator.of(context).canPop()) { pop(); popUntilRoot(); } }
fonte
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); }
fonte