Flutter 移除所有路由
Posted
技术标签:
【中文标题】Flutter 移除所有路由【英文标题】:Flutter remove all routes 【发布时间】:2018-02-03 23:20:47 【问题描述】:我想开发一个注销按钮,它会将我发送到登录路径并从Navigator
中删除所有其他路径。该文档似乎没有解释如何制作 RoutePredicate
或具有任何类型的 removeAll 功能。
【问题讨论】:
【参考方案1】:我能够使用以下代码完成此操作:
Navigator.of(context)
.pushNamedAndRemoveUntil('/login', (Route<dynamic> route) => false);
这里的秘密是使用一个总是返回 false (Route<dynamic> route) => false
的 RoutePredicate。在这种情况下,它会删除所有路由,除了我推送的新 /login
路由。
【讨论】:
非常感谢它成功了。能不能发个链接,让我了解更多。。。。 我遇到了这个问题!在 ios 上,通过使用本机视图作为小部件,在使用您的方法后,本机视图无法正确处理并继续存在,因此我有一个视图将永远不会再次在某种背景下运行并且无法处理.这似乎只发生在 iOS 设备上。 @LorenzoImperatrice 您找到解决此问题的方法了吗?我有类似的问题 即使使用了这个,我仍然有打开的实例。还有其他解决方案来推送屏幕并删除堆栈的其余部分吗? 我们如何使用这种方法传递参数。【参考方案2】:我可以使用以下代码 sn-p :
Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) =>
LoginScreen()), (Route<dynamic> route) => false),
如果要删除推送路由下面的所有路由,RoutePredicate总是返回false,例如(Route route) => false .
【讨论】:
如果你想在导航页面上发送参数,那么你可以使用 "Navigator.pushNamedAndRemoveUntil(context, "/newRouteName", (r) => false, arguments: "arg_1": firstArgument, " arg_2": secondArgument );"【参考方案3】:另一种选择是popUntil()
Navigator.of(context).popUntil(ModalRoute.withName('/root'));
这将弹出所有路线,直到您返回指定路线。
【讨论】:
我更喜欢这个答案!【参考方案4】:另一种解决方案是使用pushAndRemoveUntil()
。要删除所有其他路由,请使用ModalRoute.withName('/')
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (BuildContext context) => Login()),
ModalRoute.withName('/')
);
参考:https://api.flutter.dev/flutter/widgets/NavigatorState/pushAndRemoveUntil.html
【讨论】:
【参考方案5】:如果您想返回特定屏幕并且不使用命名路由器,可以使用下一个方法
例子:
Navigator.pushAndRemoveUntil(context,
MaterialPageRoute(builder: (BuildContext context) => SingleShowPage()),
(Route<dynamic> route) => route is HomePage
);
使用 route is HomePage,您可以检查小部件的名称。
【讨论】:
什么是 NoAnimatedRoute?在 Flutter 中找不到具有此类名称的类 @kashlo 不要注意 =) 只是我的实现可以改用 MaterialPageRoute。但我已经编辑了答案,谢谢。 (Route如果您使用的是命名路由,您可以简单地做到这一点:
Navigator.pushNamedAndRemoveUntil(context, "/login", (Route<dynamic> route) => false);
其中 "/login" 是您要推送到路由堆栈上的路由。
请注意:
此语句删除堆栈中的所有路由,并将推送的路由作为根。
【讨论】:
【参考方案7】:我不知道为什么没有人提到使用SchedularBindingInstance 的解决方案,虽然聚会有点晚了,我认为这最初是正确的做法answered here
SchedulerBinding.instance.addPostFrameCallback((_) async
Navigator.of(context).pushNamedAndRemoveUntil(
'/login',
(Route<dynamic> route) => false);
);
上面的代码删除了所有路由并导航到'/login',这也确保在通过调度回调导航到新路由之前渲染所有帧
【讨论】:
【参考方案8】:不确定我这样做是否正确
但这适合我弹出直到根小部件的用例
void popUntilRoot(Object result)
if (Navigator.of(context).canPop())
pop();
popUntilRoot();
【讨论】:
我喜欢这个答案,以防您不使用命名路由。如此优雅Object result
参数如何使用?这个功能需要吗?【参考方案9】:
在我的情况下,这个解决方案有效:
Navigator.pushNamedAndRemoveUntil(" The Route you want to go to " , (Route route) => false);
【讨论】:
如果你想去登录或注册你可以简单地调用root :::: Navigator.pushNamedAndRemoveUntil("/ " , (Route route) => false);【参考方案10】:这对我有用。实际上,我正在使用 bloc 但我的问题是登录屏幕块。注销后没有更新。它保存着以前的模型数据。甚至,我输入了错误的条目它要进入主屏幕。
第 1 步:
Navigator.of(context).pushNamedAndRemoveUntil(
UIData.initialRoute, (Route<dynamic> route) => false);
在哪里,
UIData.initialRoute = "/" or "/login"
第 2 步:
正在刷新屏幕。如果您正在使用 Bloc,那么这将非常有帮助。
runApp(MyApp());
在哪里,
MyApp() is the root class.
根类(即 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());
这是我的注销方法,
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());
【讨论】:
【参考方案11】:首先查看 chrislondon 的答案,然后知道如果您无权访问(上下文),您也可以这样做。
navigatorKey.currentState.pushNamedAndRemoveUntil('/login', (Route<dynamic> route) => false);
【讨论】:
【参考方案12】: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);
【讨论】:
【参考方案13】:就我而言,我有这幅画 第 1 页(主要)-> 第 2 页 -> 第 3 页 -> 第 4 页。
当我不得不去第4页时,第2页和返回的第3页不必出现,但我必须再次转到第1页。此时我转到第 4 页:
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
Workout()),
(Route<dynamic> route) => route.isFirst);
说明是:转到第 4 页(锻炼)并删除所有以前的页面,最多为 1,即(主)。
在您的情况下,可以从任何东西切换到登录,然后:
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
Login()),
(Route<dynamic> route) => false);
也就是去Login,把之前的所有页面都去掉,因为有false。
【讨论】:
以上是关于Flutter 移除所有路由的主要内容,如果未能解决你的问题,请参考以下文章