Flutter eliminar todas las rutas

98

Quiero desarrollar un botón de cierre de sesión que me enviará a la ruta de inicio de sesión y eliminará todas las demás rutas del archivo Navigator. La documentación no parece explicar cómo hacer RoutePredicateo tener algún tipo de función removeAll.

chrislondon
fuente

Respuestas:

267

Pude lograr esto con el siguiente código:

Navigator.of(context)
    .pushNamedAndRemoveUntil('/login', (Route<dynamic> route) => false);

El secreto aquí es usar un RoutePredicate que siempre devuelve falso (Route<dynamic> route) => false. En esta situación, elimina todas las rutas excepto la nueva /loginruta que presioné.

chrislondon
fuente
1
Muchas gracias funcionó con éxito. ¿Podría enviar algún enlace, donde pueda entender más ...?
Pawan
¡Tengo un problema con esto! En iOS, al usar una vista nativa como widget, después de usar su método, la vista nativa no se elimina correctamente y continúa existiendo, como resultado, tengo una vista que nunca se volverá a usar ejecutándose en una especie de fondo e imposible de eliminar . Esto parece suceder solo en dispositivos iOS.
Lorenzo Imperatrice
@LorenzoImperatrice ¿Encontraste una solución para este problema? Tengo un problema similar
Mateusz Tylman
3
Todavía tengo instancias abiertas incluso después de usar esto. ¿Alguna otra solución para empujar la pantalla y quitar el resto de la pila?
Manoj MM
¿Cómo podemos pasar argumentos con este enfoque?
Developine
78

Puedo hacerlo con el siguiente fragmento de código:

 Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) =>
    LoginScreen()), (Route<dynamic> route) => false),

si desea eliminar toda la ruta debajo de la ruta presionada, RoutePredicate siempre devuelve falso , por ejemplo, (Ruta de ruta) => falso .

amir khan
fuente
24

Otra alternativa es popUntil()

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

Esto quitará todas las rutas hasta que regrese a la ruta nombrada.

nleslie
fuente
1
¡Prefiero esta respuesta!
noviembre
10

En caso de que desee volver a la pantalla en particular y no use el enrutador con nombre, puede usar el siguiente enfoque

Ejemplo:

Navigator.pushAndRemoveUntil(context,
                  MaterialPageRoute(builder: (BuildContext context) => SingleShowPage()),
                  (Route<dynamic> route) => route is HomePage
              );

Con route is HomePage verificas el nombre de tu widget.

Volodymyr Bilovus
fuente
¿Qué es NoAnimatedRoute? No puedo encontrar una clase con ese nombre en Flutter
kashlo
@kashlo No prestes atención =) Es solo que mi implementación puede usar MaterialPageRoute en su lugar. Pero he editado la respuesta, gracias.
Volodymyr Bilovus
(Route <dynamic> route) => route.isFirst) Si alguno quiere eliminar hasta la primera ruta.
Hussnain Haidar
4

Si está utilizando namedRoutes, puede hacer esto simplemente:

Navigator.pushNamedAndRemoveUntil(context, "/login", (Route<dynamic> route) => false);

Donde "/ login" es la ruta que desea insertar en la pila de rutas.

Tenga en cuenta que :

Esta declaración elimina todas las rutas en la pila y hace que la empujada sea la raíz.

Kelvin Mboto
fuente
3

No sé por qué nadie mencionó la solución usando SchedularBindingInstance.Sin embargo, un poco tarde para la fiesta, creo que esta sería la forma correcta de hacerlo originalmente respondida aquí

    SchedulerBinding.instance.addPostFrameCallback((_) async {
                              Navigator.of(context).pushNamedAndRemoveUntil(
                                  '/login',
                                  (Route<dynamic> route) => false);
                            });

El código anterior elimina todas las rutas y navega a '/ login' esto también asegura que todos los marcos se rendericen antes de navegar a la nueva ruta programando una devolución de llamada

maheshmnj
fuente
1

Esto es trabajo para mí. En realidad, estaba trabajando con bloc pero mi problema era bloc de pantalla de inicio de sesión. No se estaba actualizando después de cerrar la sesión. Tenía los datos del modelo anterior. Incluso, ingresé la entrada incorrecta. Iba a la pantalla de inicio.

Paso 1:

Navigator.of(context).pushNamedAndRemoveUntil(
        UIData.initialRoute, (Route<dynamic> route) => false);

dónde, UIData.initialRoute = "/" or "/login"

Paso 2:

Está trabajando para actualizar la pantalla. Si está trabajando con Bloc, será muy útil.

runApp(MyApp());

dónde, MyApp() is the root class.

Código de clase raíz (es decir, 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());

Aquí está Mi método de cierre de sesión ,

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());
  }
estrella de rock
fuente
0

No estoy seguro de si estoy haciendo esto bien

pero esto se adapta a mi caso de uso de hacer estallar hasta que el widget raíz

void popUntilRoot({Object result}) {
    if (Navigator.of(context).canPop()) {
      pop();
      popUntilRoot();
    }
}
Vinesh Raju
fuente
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
fuente