一尘不染

请求的导航器操作的上下文不包含导航器

flutter

我正在尝试在onTap中启动新屏幕,但出现以下错误:

请求的导航器操作使用了不包含导航器的上下文。

我用来导航的代码是:

onTap: () { Navigator.of(context).pushNamed('/settings'); },

我已经在我的应用程序中设置了一条路线,如下所示:

routes: <String, WidgetBuilder>{
    '/settings': (BuildContext context) => new SettingsPage(),
},

我尝试使用stocks示例应用程序复制代码。我查看了Navigator and
Route文档,但无法弄清楚如何使上下文包含Navigator。的context在使用的onTap感从传递到构建方法中的参数引用:

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),
  );
 }
}

阅读 301

收藏
2020-08-13

共1个答案

一尘不染

TLDR
:将需要访问的小部件包装NavigatorBuilder或将子树提取到类中。并使用新BuildContext的访问Navigator


此错误与目的地无关。发生这种情况是因为您使用了一个context不包含Navigator实例的父对象。

然后如何创建Navigator实例?

这通常是通过在窗口小部件树中插入MaterialApp或来完成的WidgetApp。虽然您可以Navigator直接使用手动方式进行操作,但建议不要这样做。然后,此类小部件的所有子级都可以NavigatorState使用进行访问Navigator.of(context)

等等,我已经有一个MaterialApp/ WidgetApp

很有可能是这种情况。但是,当您使用/ context的父级时,仍然会发生此错误。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传递给buildMyApp

问题是,MyApp实际上是的父母MaterialApp。实例化的是小部件MaterialApp!因此,MyApp‘s
BuildContext没有MaterialApp父母!

要解决此问题,我们需要使用不同的context

在这种情况下,最简单的解决方案是引入一个新的小部件作为的子代MaterialApp。然后使用该小部件的上下文进行Navigator调用。

有几种方法可以实现此目的。您可以提取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, "/"),
              ),
            ),
      ),
    );
  }
}
2020-08-13