Flutter remove todas as rotas

107

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 RoutePredicateou ter qualquer tipo de função removeAll.

chrislondon
fonte

Respostas:

277

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 /loginrota que empurrei.

chrislondon
fonte
1
Muito obrigado, funcionou com sucesso. Você poderia, por favor, enviar algum link, onde eu possa entender mais ...
Pawan
Eu tenho um problema com isso! No iOS, ao usar uma visão nativa como widget, após usar seu método a visão nativa não é descartada corretamente e continua existindo, como resultado eu tenho uma visão que nunca mais será usada rodando em uma espécie de fundo e impossível de ser descartada . Isso parece acontecer apenas em dispositivos iOS.
Lorenzo Imperatrice
@LorenzoImperatrice Você encontrou uma solução para esse problema? Estou tendo um problema semelhante
Mateusz Tylman
3
Ainda tenho instâncias abertas mesmo depois de usar isso. alguma outra solução para empurrar a tela e remover o resto da pilha?
Manoj MM de
Como podemos passar argumentos com essa abordagem.
Developine
85

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 .

amir khan
fonte
27

Outra alternativa é popUntil()

Navigator.of(context).popUntil(ModalRoute.withName('/root'));

Isso removerá todas as rotas até que você retorne à rota nomeada.

Nleslie
fonte
1
Eu prefiro essa resposta!
noveleven
13

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.

Volodymyr Bilovus
fonte
o que é NoAnimatedRoute? Não consigo encontrar uma aula com esse nome no Flutter
kashlo
@kashlo Não preste atenção =) Apenas a minha implementação pode usar MaterialPageRoute. Mas eu editei a resposta, obrigado.
Volodymyr Bilovus
(Route <dynamic> route) => route.isFirst) Se algum deseja remover até a primeira rota.
Hussnain Haidar
7

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.

Kelvin Mboto
fonte
5

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

maheshmnj
fonte
2

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());
  }
estrela do rock
fonte
0

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();
    }
}
Vinesh Raju
fonte
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);
}
sj
fonte