转载 

flutter Navigator operation requested with a context that does not include a Navigator. 原理及方案

分类:android    260人阅读    IT小君  2019-01-11 22:03

flutter 最容易报的一个错误就是does not include,因为其思想是组合

这种情况即使是外面包裹了materialapp也是无效的,因为flutter会根据这个context一直上溯,一直到根节点的widget,注意,上溯是根据context的,会上溯到这个context相关的widget的最根节点


This error is unrelated to the destination. It happens because you used a context that doesn't contain a Navigator instance as parent.

How do I create a Navigator instance then ?

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).

Wait, I already have a MaterialApp/WidgetApp !

That's most likely the case. But this error can still happens when you use a context that is a parent of MaterialApp/WidgetApp.

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.

So, how do I fix it ?

First, let's reproduce this error :

  1. import 'package:flutter/material.dart';
  2. void main() => runApp(MyApp());
  3. class MyApp extends StatelessWidget {
  4. @override
  5. Widget build(BuildContext context) {
  6. return MaterialApp(
  7. home: Center(
  8. child: RaisedButton(
  9. child: Text("Foo"),
  10. onPressed: () => Navigator.pushNamed(context, "/"),
  11. ),
  12. ),
  13. );
  14. }
  15. }

This example creates a button that attempts to go to '/' on click but will instead throw an exception.

Notice here that in the

 onPressed: () => Navigator.pushNamed(context, "/"),

we used context passed by to build of MyApp.

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!

To solve this problem, we need to use a different context.

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.

There are a few ways to achieve this. You can extract home into a custom class :

  1. import 'package:flutter/material.dart';
  2. void main() => runApp(MyApp());
  3. class MyApp extends StatelessWidget {
  4. @override
  5. Widget build(BuildContext context) {
  6. return MaterialApp(
  7. home: MyHome()
  8. );
  9. }
  10. }
  11. class MyHome extends StatelessWidget {
  12. @override
  13. Widget build(BuildContext context) {
  14. return Center(
  15. child: RaisedButton(
  16. child: Text("Foo"),
  17. onPressed: () => Navigator.pushNamed(context, "/"),
  18. ),
  19. );
  20. }
  21. }

Or you can use Builder :

  1. import 'package:flutter/material.dart';
  2. void main() => runApp(MyApp());
  3. class MyApp extends StatelessWidget {
  4. @override
  5. Widget build(BuildContext context) {
  6. return MaterialApp(
  7. home: Builder(
  8. builder: (context) => Center(
  9. child: RaisedButton(
  10. child: Text("Foo"),
  11. onPressed: () => Navigator.pushNamed(context, "/"),
  12. ),
  13. ),
  14. ),
  15. );
  16. }
  17. }

 

点击广告,支持我们为你提供更好的服务

HTML5 Canvas竖直流动线条背景动画特效

html5 svg夜空中星星流星动画场景特效

网页设计开发公司网站模板

css+js实现的颜色渐变数字时钟动画特效

响应式咖啡饮品宣传网站模板

小众时尚单品在线电子商务网站模板

现代时尚家具公司网站模板

jQuery右端悬浮带返回顶部特效

js+css3抽奖转盘旋转点餐代码

html5 canvas彩色碎片组合球形旋转动画特效

有机水果蔬菜HTML5网站模板

HTML5现代家居装潢公司网站模板

html5 canvas进度条圆环图表统计动画特效

中小型创意设计服务公司网站模板

响应式时尚单品在线商城网站模板

css鼠标跟随文字模糊特效

canvas炫酷鼠标移动文字粒子特效

html5图标下拉搜索框自动匹配代码

响应式太阳能能源公司网站模板

HTML5数字产品服务公司网站模板

点击广告,支持我们为你提供更好的服务
 工具推荐 更多»
点击广告,支持我们为你提供更好的服务