flutter Navigator的进阶使用:执行数据传输等任务
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前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。