Code前端首页关于Code前端联系我们

flutter Navigator的进阶使用:执行数据传输等任务

terry 2年前 (2023-09-22) 阅读数 84 #移动小程序

flutter中的router是一个widget,但在Android中,router是一个event,在IOS中,router是一个ViewController。

除了前面提到的push、pop的方法之外,路由器还有更高级的用途。让我们来看看。

命名路由

虽然Flutter中的路由器以堆栈的形式存储路由器,并且只有push和pop可以工作,但路由器实际上可以有名称。

试想,如果Router没有名字,如何进行跳转呢?不可能每次都创建一个新路由器。

navigator 有一个名为 Navigator 的方法。pushNamed()用于将命名的Router压入堆栈。我们看一下它的定义:

  static Future<T?> pushNamed<T extends Object?>(
    BuildContext context,
    String routeName, {
    Object? arguments,
  }) {
    return Navigator.of(context).pushNamed<T>(routeName, arguments: arguments);
  }
复制代码

这个方法需要传递上下文和对应的路径名,还可以带一些参数。

那么这个方法怎么用呢?

首先我们需要定义一些路由器。例如,在创建MaterialApp时,我们可以传入一个名为Routers的路由器参数:

MaterialApp(
  title: '这是named Routers',
  initialRoute: '/firstPage',
  routes: {
    '/firstPage': (context) => const FirstPage(),
    '/secondPage': (context) => const SecondPage(),
  },
)
复制代码

在上面的代码中,我们定义了两个路由器,第一页和第二页。每个都对应一个特定的小部件。

定义完路由器后,可以这样使用:

onPressed: () {
  Navigator.pushNamed(context, '/secondPage');
}
复制代码

如果想返回首页,可以调用Navigator模式。pop实现:

onPressed: () {
  Navigator.pop(context);
}
复制代码

将参数传递给named路。

上一节讲push命名时,我们还提到它也可以接收参数。从定义中我们可以看出,概念类型是Object对象,这意味着任何对象都可以作为命名路径中的参数。

然后我们指定如下内容:

class TestArguments {
  final String name;
  final String description;

  TestArguments(this.name, this.description);
}
复制代码

接下来我们需要创建一个可以接受此参数的路由器。

由于所有路由器都是小部件,因此我们需要创建一个小部件并接收进入该小部件的参数。

向flutter传递参数有两种方式。您可以使用 ModalRoute.of() 或 onGenerateRoute()。

我们先看一下ModalRoute.of的定义:

  static ModalRoute<T>? of<T extends Object?>(BuildContext context) {
    final _ModalScopeStatus? widget = context.dependOnInheritedWidgetOfExactType<_ModalScopeStatus>();
    return widget?.route as ModalRoute<T>?;
  }
复制代码

它接收一个上下文参数,然后返回一个路由对象。

具体用法如下:

class FirstPage extends StatelessWidget {
  const FirstPage({super.key});

  static const routeName = '/firstPage';

  @override
  Widget build(BuildContext context) {

    final args = ModalRoute.of(context)!.settings.arguments as TestArguments;

    return Scaffold(
      appBar: AppBar(
        title: Text(args.name),
      ),
      body: Center(
        child: Text(args.description),
      ),
    );
  }
}
复制代码

除了使用ModalRoute之外,还可以向onGenerateRoute()方法传递参数。 onGenerateRoute 在生成 Route 时触发:

MaterialApp(

  onGenerateRoute: (settings) {
   
    if (settings.name == FirstPage.routeName) {
 
      final args = settings.arguments as TestArguments;

      return MaterialPageRoute(
        builder: (context) {
          return TestArguments(
            title: args.title,
            message: args.message,
          );
        },
      );
    }
    return null;
  },
)
复制代码

onGenerateRoute 获取一个配置对象,我们需要在设置对象中设置名称和相应的参数。所以我们需要这样调用:

    Navigator.pushNamed(
      context,
      FirstPage.routeName,
      arguments: TestArguments(
        '测试',
        '这是一个named Route',
      ),
    );
复制代码

从Screen返回值

有时我们需要从一个Screen返回到上一个Screen,这不是简单的返回。我们还想知道上一屏返回了什么结果,然后我们可以对上一屏返回的其他结果进行不同的处理。

现在您需要使用导航器。pop的参数传递函数。

例如点击第一页的按钮,跳转到第二页:

  final result = await Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => const SecondScreen()),
    );
复制代码

这里使用了Navigator.push方法,返回了结果值。

我们可以利用这个值来进行系统的判断。

那么这个产品的价值在哪里呢?

是的,第二屏幕上的导航器。pop风格:

Navigator.pop(context, 'Yes');
复制代码

这里的“是”将被发送到答案以做出合乎逻辑的决定。

向Screen传值

有时候我们在页面跳转的过程中需要传递一些参数,那么如何实现Screen之间的参数传递呢?

由于flutter中的Router都是widget,所以我们在跳转到新页面时可以直接向form builder中的Routers widget传递参数。

例如我们有如下的屏幕小部件:

class NameScreen extends StatelessWidget {

  const NameScreen({super.key, required this.name});

  final String name;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('NameScreen'),
      ),

      body: 
      ...
      ;
  }
}
复制代码

如果你想给它传递一个值,可以在 onTap 方法中写入:

onTap: () {
        Navigator.push(
          context,
          MaterialPageRoute(
            builder: (context) => NameScreen(name: 'what is your name?'),
          ),
        );
复制代码

总结

以上是 Navigator 的高级用法更好。我们可以使用 Navigator 来执行数据传输之类的任务,以实现更复杂的页面任务。作者:Programming Items
来源:稀土掘金

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门