【问题标题】:Flutter remove all routesFlutter 移除所有路由
【发布时间】:2018-02-03 23:20:47
【问题描述】:

我想开发一个注销按钮,它会将我发送到登录路径并从Navigator 中删除所有其他路径。该文档似乎没有解释如何制作 RoutePredicate 或具有任何类型的 removeAll 功能。

【问题讨论】:

    标签: dart flutter


    【解决方案1】:

    我能够使用以下代码完成此操作:

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

    这里的秘密是使用一个总是返回 false (Route&lt;dynamic&gt; route) =&gt; 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 route) => route.isFirst) 如果有人想删除直到第一条路线。
      【解决方案6】:

      如果您使用的是命名路由,您可以简单地做到这一点:

      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。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2021-01-31
                  • 1970-01-01
                  • 1970-01-01
                  • 2020-08-26
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2019-10-28
                  相关资源
                  最近更新 更多