我正在尝试在onTap中启动新屏幕,但出现以下错误:
请求的导航器操作使用了不包含导航器的上下文。
我用来导航的代码是:
onTap: () { Navigator.of(context).pushNamed('/settings'); },
我已经在我的应用程序中设置了一条路线,如下所示:
routes: <String, WidgetBuilder>{ '/settings': (BuildContext context) => new SettingsPage(), },
我尝试使用stocks示例应用程序复制代码。我查看了Navigator and Route文档,但无法弄清楚如何使上下文包含Navigator。的context在使用的onTap感从传递到构建方法中的参数引用:
context
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) {
SettingsPage是如下类:
class SettingsPage extends Navigator { Widget buildAppBar(BuildContext context) { return new AppBar( title: const Text('Settings') ); } @override Widget build(BuildContext context) { return new Scaffold( appBar: buildAppBar(context), ); } }
TLDR :将需要访问的小部件包装Navigator到Builder或将子树提取到类中。并使用新BuildContext的访问Navigator。
Navigator
Builder
BuildContext
此错误与目的地无关。发生这种情况是因为您使用了一个context不包含Navigator实例的父对象。
然后如何创建Navigator实例?
这通常是通过在窗口小部件树中插入MaterialApp或来完成的WidgetApp。虽然您可以Navigator直接使用手动方式进行操作,但建议不要这样做。然后,此类小部件的所有子级都可以NavigatorState使用进行访问Navigator.of(context)。
MaterialApp
WidgetApp
NavigatorState
Navigator.of(context)
等等,我已经有一个MaterialApp/ WidgetApp!
很有可能是这种情况。但是,当您使用/ context的父级时,仍然会发生此错误。MaterialApp``WidgetApp
MaterialApp``WidgetApp
发生这种情况是因为,当您这样做时Navigator.of(context),它将从与已context使用的小部件关联的小部件开始。然后在小部件树中向上移动,直到找到一个Navigator或没有其他小部件。
在第一种情况下,一切都很好。在第二个中,它抛出一个
那么,我该如何解决呢?
首先,让我们重现此错误:
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Center( child: RaisedButton( child: Text("Foo"), onPressed: () => Navigator.pushNamed(context, "/"), ), ), ); } }
本示例创建一个按钮,该按钮尝试单击时转到“ /”,但将引发异常。
请注意,在
onPressed: () => Navigator.pushNamed(context, "/"),
我们过去context传递给build的MyApp。
build
MyApp
问题是,MyApp实际上是的父母MaterialApp。实例化的是小部件MaterialApp!因此,MyApp‘s BuildContext没有MaterialApp父母!
要解决此问题,我们需要使用不同的context。
在这种情况下,最简单的解决方案是引入一个新的小部件作为的子代MaterialApp。然后使用该小部件的上下文进行Navigator调用。
有几种方法可以实现此目的。您可以提取home到自定义类中:
home
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: MyHome() ); } } class MyHome extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: RaisedButton( child: Text("Foo"), onPressed: () => Navigator.pushNamed(context, "/"), ), ); } }
或者您可以使用Builder:
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Builder( builder: (context) => Center( child: RaisedButton( child: Text("Foo"), onPressed: () => Navigator.pushNamed(context, "/"), ), ), ), ); } }