Dart 如何检查当前路线是哪条?

Dart 如何检查当前路线是哪条?,dart,flutter,Dart,Flutter,我希望使用抽屉导航到不同的路由,但如果我已经在某个路由上,我不希望每次点击该路由时都打开该路由的新实例,而是希望在这种情况下不打开新路由。这是我目前的代码: Widget build(BuildContext context){ return new Drawer( child: new ListView( children: <Widget>[ new ListTile(

我希望使用抽屉导航到不同的路由,但如果我已经在某个路由上,我不希望每次点击该路由时都打开该路由的新实例,而是希望在这种情况下不打开新路由。这是我目前的代码:

Widget build(BuildContext context){
    return new Drawer(
      child:
          new ListView(
            children: <Widget>[
              new ListTile(
                title: new Text("NewRoute"),
                onTap: () {
                    Navigator.of(context).pop;
                    Navigator.of(context).pushNamed('/NewRoute');
                }
              )
           )
     )
}
小部件构建(构建上下文){
归还新抽屉(
儿童:
新列表视图(
儿童:[
新ListTile(
标题:新文本(“新路线”),
onTap:(){
Navigator.of(context.pop);
Navigator.of(context.pushNamed('/NewRoute');
}
)
)
)
}
我想使用一个条件语句来检查我们是否在某个路由上。我知道有一种方法可以通过route类的isCurrent来检查我们当前在哪个路由上

虽然我不知道如何实施它


提前感谢!

Navigator
不会公开当前路线

您可以改为使用
Navigator.popUtil(callback)
作为
popUtil
向回调传递当前的
路由,其中包括它的名称和内容

final newRouteName = "/NewRoute";
bool isNewRouteSameAsCurrent = false;

Navigator.popUntil(context, (route) {
  if (route.settings.name == newRouteName) {
    isNewRouteSameAsCurrent = true;
  }
  return true;
});

if (!isNewRouteSameAsCurrent) {
  Navigator.pushNamed(context, newRouteName);
}

使用以下代码检查路线是否位于最顶端

 Route route = MaterialPageRoute(builder: (context) => WidgetName());
 if(route.isCurrent){
 }
真的帮助了我,但如果你像我一样是新手,需要一段时间才能理解。下面是我的版本,附带一些额外的检查和说明文档:

/// Navigates through the application. Only replaces the top Route if it is
/// different from the new Route. Always keeps the home page as base of the
/// Navigator stack. New screens are pushed on the Navigator stack. When the
/// user switches between non-home screens, the new screen replaces the old
/// screen. In this way, the stack of screens from the drawer is never higher
/// than 2. Returning to the HomeScreen is done by just popping the current
/// Route.
void _changeRoute(BuildContext context, String newRouteName) {
  // Close drawer
  Navigator.pop(context);

  // Check current screen status
  bool currentRouteIsHome = false;
  bool currentRouteIsNewRoute = false;

  Navigator.popUntil(context, (currentRoute) {
    // This is just a way to access currentRoute; the top route in the 
    // Navigator stack.
    if (currentRoute.settings.name == HomeScreen.ROUTE_NAME) {
      currentRouteIsHome = true;
    }
    if (currentRoute.settings.name == newRouteName) {
      currentRouteIsNewRoute = true;
    }

    // Return true so popUntil() pops nothing.
    return true;
  });

  // Switch screen
  if (!currentRouteIsNewRoute) {
    // Only switch screen if new route is different from current route.
    if (currentRouteIsHome) {
      // Navigate from home to non-home screen.
      Navigator.pushNamed(context, newRouteName);
    } else {
      if (newRouteName == HomeScreen.ROUTE_NAME) {
        // Navigate from non-home screen to home.
        Navigator.pop(context);
      } else {
        // Navigate from non-home screen to non-home screen.
        Navigator.popAndPushNamed(context, newRouteName);
      }
    }
  }
}
请注意,此带有
pushNamed
popandpushname
的实现要求您在
routes:
参数的顶级
MaterialApp
中定义
Route
名称,如下所示:

new MaterialApp(
  routes: <String, WidgetBuilder>{
    // define the routes
    YOUR_SCREEN_ROUTE_NAME: (BuildContext context) => new YourScreen(),
  },
)
新材料聚丙烯(
路线:{
//定义路线
您的屏幕路径名称:(BuildContext context)=>newyourscreen(),
},
)
我正在使用此代码

*Route route = MaterialPageRoute(builder: (context) => Myinternet());
 print(route.isCurrent);
 if(route.isCurrent){
 }*
输出:

显示始终错误当前页面未找到


这将为您提供确切的路由名称

import 'package:path/path.dart';

ModalRoute.of(context).settings.name
要避免null异常,请执行以下操作

var route = ModalRoute.of(context);

if(route!=null){
    print(route.settings.name);
 }
这是我的解决方案

void redirect(screen){
  Navigator.popUntil(context, (route) {
    if ( route.settings.name != screen) {
      Navigator.pushNamed(context, screen);
    }
    return true;
  });
}

是一个很好的API来解决这个问题,但它不能在initState()中使用;

对我来说,我使用的是最懒的方法,因为这里没有答案在主路由中对我有帮助,我只使用drawer类并将当前路由的名称传递给drawer构造函数,如下所示:

class MyDrawer extends StatelessWidget {
final String currentRoute;
MyDrawer(this.currentRoute);

@override
Widget build(BuildContext context) {
return Drawer(
    child: ListView(
      children: <Widget>[
        InkWell(
            child: Text('secondRoute'),
            onTap: () {
              if (currentRoute != 'secondRoute')
              Navigator.push(context,
                  MaterialPageRoute(builder: (context) => secondRoute()));
            }),
        InkWell(
            child: Text('thirdRoute'),
            onTap: () {
              if (currentRoute != 'thirdRoute')
              Navigator.push(context,
                  MaterialPageRoute(builder: (context) => thirdRoute()));
            }),

这是Dart扩展方法的完美用例(基于Rémi Rousselet的回答):

然后它看起来像这样干净:

Navigator.of(context).pushNamedIfNotCurrent('/NewRoute');

这是我的解决方案。基于Rémi Rousselet解决方案。 唯一的区别是防止“最后”路线的弹出

bool routeFound = false;
String routeName = "/myRoute";

//remove all the routes and stops if find the routeName or if is the last one
Navigator.popUntil(context, (route) {
    if (route.settings.name == routeName) {
        expenseRouteFound = true;
    }
    //print("route " + routeName + " founded in stack: " + routeFound.toString());
    //print("last remaining route into the stack: " + route.isFirst.toString());

    return routeFound || route.isFirst;
});

//print("route " + routeName + " founded in stack: " + routeFound.toString());
if (!routeFound) {
    //print("time to push the route: " + routeName + "!");
    Navigator.of(context).pushNamedAndRemoveUntil(routeName, (_)=>false);
}

你可以用一个:

Get.currentRoute
使用此软件包:

你会有现在的路线

但是,您不需要这样做,因为与标准的颤振不同,Get可以防止用户意外地单击按钮两次(如果用户使用的是低成本设备,则会在发出咔嗒声后发生)。 然后您只需要使用:
Get.to(Home());
并且准备就绪,就可以完成了

目前,由于这个原因,Getx对于具有颤振的项目实际上是不可或缺的。 我看了所有的问题,它们都很酷,但它们通常涉及使用PopTill来访问路由,当其他开发人员阅读您的代码时,这看起来像是一种黑客行为。 使用GetX,您将不会出现这种双击问题,因为如果您使用Get.to(page(),preventDuplicates:false)明确禁用它,它只会导航到同一页面的另一个页面; 记住这是例外情况,在您的情况下,您可以简单地使用: Get.to(Page());并导航到下一页,而不存在任何重复路由的风险,因为防止这种事情已经成为标准

获取当前路由似乎还需要很多样板文件,使用一个简单的:
Get.currenteRoute
,获取当前路由的名称(即使您没有命名路由,它也会为您提供它的名称)


嗯,现在回答这个问题有点晚了,但我希望您和其他阅读此文章的用户喜欢使用保留最后一个事件并将其提供给感兴趣的各方的。有趣的是,
RouteAware
方法不提供路由设置。因此,您无法使用
RouteAware
知道当前路由的名称。可能重复的小部件无法访问该路由。您不能这样做。有趣的是,当我尝试您的解决方案时(我会说非常聪明)I receive:Failed assertion:boolean表达式不能为null,尽管我绕过了Navigotor.pushNamed(context,NewRouteName)对布尔值的使用,使其正常工作;在第一个if语句中,同时将条件更改为!=。您是否忘记将
IsNewRoutesMeasCurrent
初始化为false?我初始化了它,尽管很有趣,似乎即使没有当前的布尔值开始,它仍会引发相同的异常xd您解决了空布尔异常吗?我很抱歉对同一问题进行友好处理此代码与主路由?route.settings.name一起工作,只返回
/
。避免空指针异常的更好方法:
ModalRoute.of(上下文)?.settings?.name
ModalRoute.of(上下文).settings.name在版本1.17.0 releasebuild中以小部件的形式返回我。但它在调试版本中运行良好。有什么想法吗?出于某种原因,Rémi Rousselet的方法对我有效,但这个方法总是为空。它是一个注释,而不是答案。请编写更多内容,否则它很快就会关闭。您可以在@override void didChangeDe中使用它pendencies(){}如果用户点击后退按钮,这是如何调用的?@TimSim使用
WillPopScope
小部件注册后退按钮按下。仅仅在移动应用程序中切换页面看起来有点疯狂…@Kirill你也可以选择使用单个脚手架,并根据抽屉的状态更新其主体,但是
Navigator.of(context).pushNamedIfNotCurrent('/NewRoute');
bool routeFound = false;
String routeName = "/myRoute";

//remove all the routes and stops if find the routeName or if is the last one
Navigator.popUntil(context, (route) {
    if (route.settings.name == routeName) {
        expenseRouteFound = true;
    }
    //print("route " + routeName + " founded in stack: " + routeFound.toString());
    //print("last remaining route into the stack: " + route.isFirst.toString());

    return routeFound || route.isFirst;
});

//print("route " + routeName + " founded in stack: " + routeFound.toString());
if (!routeFound) {
    //print("time to push the route: " + routeName + "!");
    Navigator.of(context).pushNamedAndRemoveUntil(routeName, (_)=>false);
}
Get.currentRoute