导航器通过pushNamed传递参数

时间:2018-11-14 16:05:56

标签: flutter

以前可能会被问到,但我找不到它,但是如何将参数传递给命名路由?

这就是我建立路线的方式

Widget build(BuildContext context) {
    return new Navigator(
      initialRoute: 'home/chooseroom',
      onGenerateRoute: (RouteSettings settings) {
        WidgetBuilder builder;
        switch (settings.name) {
          case 'home/chooseroom':
            // navigates to 'signup/choose_credentials'.
            builder = (BuildContext _) => new ChoosePage();
            break;
          case 'home/createpage':
            builder = (BuildContext _) => new CreateRoomPage();
            break;
          case 'home/presentation':
            builder = (BuildContext _) => new Presentation();
            break;
          default:
            throw new Exception('Invalid route: ${settings.name}');
        }
        return new MaterialPageRoute(builder: builder, settings: settings);
      },
    );

这就是你的称呼 Navigator.of(context).pushNamed('home/presentation')

但是如果我的小部件是new Presentation(arg1, arg2, arg3)怎么办?

13 个答案:

答案 0 :(得分:7)

pushNamed()现在支持自merged pull request开始的参数。如果您迫不及待,请切换到频道masterflutter channel master,然后再跟flutter upgrade)。

如何发送

    Navigator.pushNamed(ctx, '/foo', arguments: someObject);

如何接收

...
    return MaterialApp(
        ...
        onGenerateRoute: _getRoute,
        ...
    );
...

Route<dynamic> _getRoute(RouteSettings settings) {
    if (settings.name == '/foo') {
        // FooRoute constructor expects SomeObject
        return _buildRoute(settings, new FooRoute(settings.arguments));
    }

    return null;
}

MaterialPageRoute _buildRoute(RouteSettings settings, Widget builder) {
    return new MaterialPageRoute(
        settings: settings,
        builder: (ctx) => builder,
    );
}

“参数”可以是任何对象,例如地图。

答案 1 :(得分:3)

基本上,您有2个选择:

  • 使用一些第三方软件包进行路由-我认为最好是 Fluro
  • 利用onGenerateRoute。此选项仅限您可以传递的参数(字符串/数字)

要使用第二个选项,假设您要传递三个参数:Navigator.of(context).pushNamed('home/presentation:arg1:1337:hello')

MaterialApp ( 
         ... ,
         onGenerateRoute: handleRoute,
         routes:... , ) 

Route<dynamic> handleRoute(RouteSettings settings) {

    WidgetBuilder builder;

    final List<String> uri = settings.name.split('/');

    if (uri[0].startsWith('home')) {

      // handle all home routes:
      if(uri[1].startsWith('presentation:'){
         // cut slice by slice
         final String allArgs = 
               uri[1].substring('presentation:'.length);
         final List<String> args = allArgs.split(':');

          // use your string args
         print(args[0]);             // prints "arg1"
         int x = int.parse(args[1]); // becomes 1337
         print(args[2]);             // prints "hello"

         builder = (ctx)=> Presentation(args[0],args[1],args[2]);
...

答案 2 :(得分:3)

不需要onGenerateRoute。只需使用

Navigator.pushNamed(
    context,
    ImagesScreen.routeName,
    arguments: {'path': path}
);

并按如下所示提取参数:

@override
Widget build(BuildContext context) {
    final Map arguments = ModalRoute.of(context).settings.arguments as Map;
    if (arguments != null) print(arguments['path']);
    return Scaffold(...);
}

答案 3 :(得分:2)

使用从WidgetA到WidgetB的参数进行简单导航

  1. 在MaterialApp主窗口小部件中定义路线:
    return MaterialApp(
       routes: {
           '/routeAB': (context) => WidgetB(),
       },
  1. 在WidgetA中,使用pushNamed方法导航到WidgetB:
  onTap: () { 
     Navigator.pushNamed(context, '/routeAB', 
       arguments: {
          'arg1': val1,
          'arg2': val2,
          ...
  1. 在WidgetB中获取参数:
    Map args = ModalRoute.of(context).settings.arguments;

答案 4 :(得分:1)

参数可以是任何对象,可以创建一个数组,如下所示:

Navigator.of(context).pushNamed('/upload', arguments: {'_imagePath':_imagePath,
      'num_docfiscal':num_docfiscal,'dta_docfiscal':dta_docfiscal});

并访问路由器类。

答案 5 :(得分:1)

对于具有多个参数或动态对象的named Routes,您需要执行以下操作(这是MVVM模式示例):

导航器:

void navigateEditParty(int index) {
    _navigationService.navigateTo(PartyEditRoute,
        arguments: {"hunter": hunter, "index": index});
  }

路由器:

case PartyEditRoute:
  Map args = settings.arguments;
  return _getPageRoute(
    routeName: settings.name,
    viewToShow: PartyEditView(
      hunter: args["hunter"],
      index: args["index"],
    ),
  );

班级:

PartyEditView({Key key, this.hunter, this.index}) : super(key: key);

答案 6 :(得分:1)

传递参数:

Navigator.pushNamed(YourScreen.routeName, arguments: {"title":myTitle, "user_name":userName});

提取参数:

        Map<String, dynamic> arguments = new Map<String, dynamic>.from(settings.arguments);
        page = MyRecordingScreen(title: arguments["title"], tags: arguments["user_name"], );

答案 7 :(得分:0)

始终最好将参数包装在一个对象中,以避免容易出错的代码。

下面是如何用飞镖实现它的工作示例。

发送

Navigator.of(context).pushNamed(Routes.submitSuccess, arguments: successModel);

接收

  case Routes.submitSuccess:
    if (settings.arguments is SubmitSuccessModel) {//Check for instance here
      return CupertinoPageRoute(
          builder: (_) =>
              SubmitSuccessPage(successModel: settings.arguments));
    }

模型对象

class SubmitSuccessModel {
  SubmitSuccessModel(
      {this.title, this.desc, this.actionButtonName, this.widget});
  String title;
  String desc;
  String actionButtonName;
  Widget widget;
}

final SubmitSuccessModel successModel = SubmitSuccessModel(
  title: 'Title',
  desc: 'Desc',
  actionButtonName: 'Done',
);

答案 8 :(得分:0)

注意new routing options may be available soon


这可能吗?

pushRouteSettings参数一起使用,以指定命名的路由。

这样,您可以以类型安全的方式将任何类型的参数(包括对象)直接传递到目标Widget,并使用arguments跳过。您不需要create a single-use throwaway arguments class或地图。

RouteSettings中的

push可以为导航堆栈提供一个命名的Route,您可以在以后的路由决策中搜索/使用它,就像使用{{1 }}。

Push + RouteSettings

要对命名路由使用pushNamed,请在路由名称中使用push参数。

示例:用户登录RouteSettings,现在您希望Page1pushPage1

Page2调用中,将Page1对象(User)直接传递到loggedInUser中,并在您的Page2参数中使用Navigator.push参数路由名称(RouteSettings)。

/page2

在Page2小部件中,您可以期望并直接使用Navigator.push(context, MaterialPageRoute( builder: (context) => Page2(user: loggedInUser), settings: RouteSettings(name: '/page2') )); 对象。

User

以后您可以使用class Page2 extends StatefulWidget { final User loggedInUser; Page2(this.loggedInUser); @override _Page2State createState() => _Page2State(); } class _Page2State extends State<Page2> { User loggedInUser; @override void initState() { super.initState(); loggedInUser = widget.loggedInUser; print(loggedInUser.name); } @override Widget build(BuildContext context) { } } 路由名称。例如,如果您在/page2,并且想/page3,那么就可以。

引擎盖下

Flutter的popUntil(context, ModalRoute.withName('/page2'))类显示Navigator使用pushNamed + routeNamed,而push使用routeNamed

RouteSettings
Future<T> pushNamed<T extends Object>(
    String routeName, {
    Object arguments,
  }) {
    return push<T>(_routeNamed<T>(routeName, arguments: arguments));
  }

答案 9 :(得分:0)

我花了一段时间才注意到这一点,因为我是 Flutter 的新手。但是您使用 Navigator.pushNamed 添加的参数会直接发送到您推送的小部件,而不是用于路由的 MaterialApp。

您的构造函数中根本不需要这些参数。相反,您可以像其他人所说的那样在小部件中将它们拉出;即通过:

final arg = ModalRoute.of(context)!.settings.arguments as Map;

并且可以像这样分配它们:

randomVar1 = arg['v1'];
randomVar2 = arg['v2'];
randomVar3 = arg['v3'];

使用您输入的任何键。

如果您希望 MaterialApp 处理它,那么您可以使用 onGenerateRoute 方法。这让我永远注意到参数直接进入推送的小部件。对我来说,这是违反直觉的。

答案 10 :(得分:0)

我花了一段时间才注意到这一点,因为我是 Flutter 的新手。但是您使用 Navigator.pushNamed 添加的参数会直接发送到您推送的小部件,而不是用于路由的 MaterialApp。

因此,在小部件中,您将获得一个新屏幕:

Navigator.pushNamed(
   context,
   SomePage.routeName,
   arguments: {
      'v1': 'data1',
      'v2': 'data2',
      'v3': 'data3',
   },
)

您的构造函数中根本不需要这些参数。相反,您可以像其他人所说的那样在 SomePage 小部件中将它们拉出;即通过:

final arg = ModalRoute.of(context)!.settings.arguments as Map;

并且可以在 SomePage 构建中分配它们,例如:

randomVar1 = arg['v1'];
randomVar2 = arg['v2'];
randomVar3 = arg['v3'];

使用您输入的任何键。

如果您希望 MaterialApp 处理它,那么您可以使用 onGenerateRoute 方法。这让我永远注意到参数直接进入推送的小部件。对我来说,这是违反直觉的。

答案 11 :(得分:0)

screen_1.dart

Navigator.of(context).pushNamed('/screen2',arguments: {'var1': val1 ,'var2': val2, "var3": val3 ,"var4" : val4}); //sending of the values to route_generator.dart

route_generator.dart

class RouteGenerator {
  static Route<dynamic> generateRoute(RouteSettings settings) //from screeen_1.dart
{
    // Getting arguments passed in while calling Navigator.pushNamed
    Map args = settings.arguments;

switch (settings.name) {
case '/screen2':
        if (args is Map) {
          return MaterialPageRoute(
            builder: (_) => screen_2(args),
          );
        }
        return _errorRoute(); //optional written in a scaffold when any error arrises
default:
return _errorRoute(); //optional written in a scaffold when any error arrises

}

screen_2.dart

screen_2(Map args) //follow the params from the route_generator.dart
{
  return Scaffold(
    body: FutureBuilder(
        future: _screen_2EndpointProvider.fetchScreen_2(args['var1'], args["var2"], args['var3'], args['var4']),  //API call inside which it called the args 
        builder: (context, snapshot) {
          return snapshot.hasData
              ? screen_2(param: snapshot.data)
              : Center(child: CircularProgressIndicator());
        }),
  );
}

我试图提供一个简单的例子,如果它对任何人都有帮助,因为经过大量试验后我遇到了同样的错误。

答案 12 :(得分:-1)

// 我们要导航的主屏幕

Navigator.pushNamed(
                              context,
                             "/ScreenName",
                              arguments: {
                                'id': "20" 
                              });

我在使用 NavigationRoutes 时也遇到了同样的问题

class NavigationRoutes {
  static Route<dynamic> generateScreenRoute(RouteSettings settings) {
   // TODO below we are able to get Arguments list
    Map args = settings.arguments;
    
    switch (settings.name) {
      
      case "Screen Name": 
        return MaterialPageRoute(builder: (context) => ScreenName(args)); 
      // TODO pass above argument here and get in the form of Constructor in Screen 
      //   Name Class
    }

}
相关问题