使用不包含导航器的上下文请求的导航器操作 [英] Navigator operation requested with a context that does not include a Navigator

查看:122
本文介绍了使用不包含导航器的上下文请求的导航器操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在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实例?

这通常是通过在窗口小部件树中插入MaterialAppWidgetApp来完成的.虽然您可以直接使用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, "/"),

我们使用了传递给MyAppbuildcontext.

we used context passed by to build of MyApp.

问题是,MyApp实际上是MaterialApp的父级.因为实例化MaterialApp的是小部件!因此,MyAppBuildContext没有父级的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆