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.
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.
Respostas:
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 .
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
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.
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 :
Essa declaração remove todas as rotas da pilha e torna a que foi enviada a raiz.
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
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.
runApp(MyApp());
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());
}
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();
}
}