使用不包含导航器的上下文请求的导航器操作 [英] Navigator operation requested with a context that does not include a Navigator
问题描述
我正在尝试在onTap中启动新屏幕,但出现以下错误:
I'm trying to start a new screen within an onTap but I get the following error:
导航器操作请求的上下文不包含 导航器.
Navigator operation requested with a context that does not include a Navigator.
我用来导航的代码是:
onTap: () { Navigator.of(context).pushNamed('/settings'); },
我已经在我的应用中设置了一条路线,如下所示:
I have set up a route in my app as follows:
routes: <String, WidgetBuilder>{
'/settings': (BuildContext context) => new SettingsPage(),
},
我尝试使用stocks示例应用程序复制代码.我查看了Navigator和Route文档,但无法弄清楚如何使上下文包含Navigator.在onTap中使用的context
是从传递给build方法的参数中引用的:
I've tried to copy the code using the stocks sample application. I've looked at the Navigator and Route documentation and can't figure out how the context can be made to include a Navigator. The context
being used in the onTap is referenced from the parameter passed into the build method:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
SettingsPage是如下类:
SettingsPage is a class as follows:
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
.
TLDR: Wrap the widget which needs to access to Navigator
into a Builder
or extract that sub-tree into a class. And use the new BuildContext
to access Navigator
.
此错误与目的地无关.发生这种情况是因为您使用了一个不包含Navigator
实例的context
作为父对象.
This error is unrelated to the destination. It happens because you used a context
that doesn't contain a Navigator
instance as parent.
然后如何创建Navigator实例?
这通常是通过在窗口小部件树中插入MaterialApp
或WidgetApp
来完成的.虽然您可以直接使用Navigator
手动进行操作,但建议不要这样做.然后,此类小部件的所有子代都可以使用Navigator.of(context)
访问NavigatorState
.
This is usually done by inserting in your widget tree a MaterialApp
or WidgetApp
. Although you can do it manually by using Navigator
directly but less recommended. Then, all children of such widget can access NavigatorState
using Navigator.of(context)
.
等等,我已经有一个MaterialApp
/WidgetApp
了!
Wait, I already have a MaterialApp
/WidgetApp
!
最有可能是这种情况.但是,当您使用作为MaterialApp
/WidgetApp
父级的context
时,仍然会发生此错误.
That's most likely the case. But this error can still happens when you use a context
that is a parent of MaterialApp
/WidgetApp
.
之所以会发生这种情况,是因为当您执行Navigator.of(context)
时,它将从与所使用的context
关联的小部件开始.然后在小部件树中向上导航,直到找到Navigator
或没有其他小部件为止.
This happens because when you do Navigator.of(context)
, it will start from the widget associated to the context
used. And then go upward in the widget tree until it either find a Navigator
or there's no more widget.
在第一种情况下,一切都很好.在第二个中,它抛出一个
In the first case, everything is fine. In the second, it throws a
在不包含导航器的上下文中请求的导航器操作.
Navigator operation requested with a context that does not include a Navigator.
那么,我该如何解决?
首先,让我们重现此错误:
First, let's reproduce this error :
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, "/"),
),
),
);
}
}
此示例创建一个按钮,该按钮尝试单击时转到"/",但会引发异常.
This example creates a button that attempts to go to '/' on click but will instead throw an exception.
请注意
onPressed: () => Navigator.pushNamed(context, "/"),
我们使用了传递给MyApp
的build
的context
.
we used context
passed by to build
of MyApp
.
问题是,MyApp
实际上是MaterialApp
的父级.因为实例化MaterialApp
的是小部件!因此,MyApp
的BuildContext
没有父级的MaterialApp
!
The problem is, MyApp
is actually a parent of MaterialApp
. As it's the widget who instantiate MaterialApp
! Therefore MyApp
's BuildContext
doesn't have a MaterialApp
as parent!
要解决此问题,我们需要使用其他context
.
To solve this problem, we need to use a different context
.
在这种情况下,最简单的解决方案是引入一个新的小部件作为MaterialApp
的子级.然后使用该小部件的上下文进行Navigator
调用.
In this situation, the easiest solution is to introduce a new widget as child of MaterialApp
. And then use that widget's context to do the Navigator
call.
有几种方法可以实现这一目标.您可以将home
提取到自定义类中:
There are a few ways to achieve this. You can extract home
into a custom class :
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, "/"),
),
),
),
);
}
}
这篇关于使用不包含导航器的上下文请求的导航器操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!