Chcę opracować przycisk wylogowania, który wyśle mnie do trasy logowania i usunie wszystkie inne trasy z Navigator
. Dokumentacja nie wydaje się wyjaśniać, jak utworzyć RoutePredicate
lub mieć jakąkolwiek funkcję removeAll.
107
Udało mi się to osiągnąć za pomocą następującego kodu:
Navigator.of(context)
.pushNamedAndRemoveUntil('/login', (Route<dynamic> route) => false);
Sekret polega na użyciu RoutePredicate, która zawsze zwraca wartość false (Route<dynamic> route) => false
. W tej sytuacji usuwa wszystkie trasy z wyjątkiem nowej /login
trasy, którą pchnąłem.
mogę zrobić z następującym fragmentem kodu:
Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => LoginScreen()), (Route<dynamic> route) => false),
jeśli chcesz usunąć całą trasę poniżej przekazanej trasy, RoutePredicate zawsze zwraca false , np. (Route route) => false .
źródło
Inną alternatywą jest
popUntil()
Navigator.of(context).popUntil(ModalRoute.withName('/root'));
Spowoduje to wyłączenie wszystkich tras, dopóki nie wrócisz na nazwaną trasę.
źródło
Innym rozwiązaniem jest użycie
pushAndRemoveUntil()
. Aby usunąć wszystkie inne trasy, użyjModalRoute.withName('/')
Navigator.pushAndRemoveUntil( context, MaterialPageRoute(builder: (BuildContext context) => Login()), ModalRoute.withName('/') );
Źródła: https://api.flutter.dev/flutter/widgets/NavigatorState/pushAndRemoveUntil.html
źródło
Jeśli chcesz wrócić do określonego ekranu i nie używasz nazwanego routera, możesz skorzystać z następnego podejścia
Przykład:
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (BuildContext context) => SingleShowPage()), (Route<dynamic> route) => route is HomePage );
Dzięki Route to HomePage sprawdzasz nazwę swojego widżetu.
źródło
Jeśli używasz namedRoutes, możesz to zrobić po prostu:
Navigator.pushNamedAndRemoveUntil(context, "/login", (Route<dynamic> route) => false);
Gdzie „/ login” to trasa, którą chcesz umieścić na stosie tras.
Zauważ, że:
źródło
Nie wiem, dlaczego nikt nie wspomniał o rozwiązaniu za pomocą SchedularBindingInstance , Trochę spóźniony na imprezę, myślę, że byłby to właściwy sposób, aby to zrobić pierwotnie odpowiedział tutaj
SchedulerBinding.instance.addPostFrameCallback((_) async { Navigator.of(context).pushNamedAndRemoveUntil( '/login', (Route<dynamic> route) => false); });
Powyższy kod usuwa wszystkie trasy i nawigacje do '/ login', co również zapewnia, że wszystkie ramki są renderowane przed nawigacją do nowej trasy przez zaplanowanie wywołania zwrotnego
źródło
To działa dla mnie. Właściwie pracowałem z blokiem, ale moim problemem był blok ekranu logowania. Nie aktualizował się po wylogowaniu. Przechowywał dane poprzedniego modelu. Nawet wpisałem zły wpis. Przechodził do ekranu głównego.
Krok 1:
Navigator.of(context).pushNamedAndRemoveUntil( UIData.initialRoute, (Route<dynamic> route) => false);
gdzie,
UIData.initialRoute = "/" or "/login"
Krok 2:
Działa, aby odświeżyć ekran. Jeśli pracujesz z Bloc, będzie to bardzo pomocne.
gdzie,
MyApp() is the root class.
Kod klasy głównej (tj. 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());
Oto metoda 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()); }
źródło
Nie jestem pewien, czy robię to dobrze
ale to pasuje do mojego przypadku użycia poppingu do widgetu root
void popUntilRoot({Object result}) { if (Navigator.of(context).canPop()) { pop(); popUntilRoot(); } }
źródło
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); }
źródło