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.

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.


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 .


27

Outra alternativa é popUntil()

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

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


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.


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.


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


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());
  }

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();
    }
}

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);
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.