Flutter Navigator无法正常工作

时间:2018-05-01 21:50:28

标签: dart flutter

我有两个屏幕的应用程序,我想按下按钮从第一个屏幕到第二个屏幕。

屏幕1

import 'package:flutter/material.dart';
import './view/second_page.dart';

void main() => runApp(new MyApp());

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new MainScreen();
  }
}

class MainScreen extends State<MyApp> {

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
        home: new Scaffold(
            appBar: new AppBar(
                title: new Text("Title")
            ),
            body: new Center(
                child: new FlatButton(child: new Text("Second page"),
                    onPressed: () {
                      Navigator.push(context,
                          new MaterialPageRoute(
                              builder: (context) => new SecondPage()))
                    }
                )
            )
        )
    );
  }
}

屏幕2

import 'package:flutter/material.dart';

class SecondPage extends StatefulWidget {

  @override
  State<StatefulWidget> createState() {
    return new SecondPageState();
  }
}


class SecondPageState extends State<SecondPage> {

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Title"),
      ),
      body: new Center(
        child: new Text("Some text"),
      ),
    );
  }
}

推动没有发生,我得到了这个

  

处理手势时抛出以下断言:导航器   请求的操作使用不包含导航器的上下文。   用于从导航器中推送或弹出路由的上下文必须是这样的   作为Navigator小部件后代的小部件。

     

抛出另一个异常:使用a请求导航器操作   不包含导航器的上下文。

有什么问题?

7 个答案:

答案 0 :(得分:10)

将Flutter中的小部件视为树,上下文指向使用构建函数构建的任何节点。在你的情况下,你有

MainScreen    <------ context
  --> MaterialApp
   (--> Navigator built within MaterialApp)
      --> Scaffold
        --> App Bar
          --> ...
        --> Center
          --> FlatButton

因此,当您使用上下文查找导航器时,您正在使用MainScreen的上下文,该上下文不在导航器下。

您可以创建一个新的Stateless或Stateful Widget子类来包含您的Center + FlatButton,因为其中的构建函数将指向该级别,或者您可以使用Builder并定义{{1回调(具有指向Builder的上下文)以返回Center + FlatButton。

答案 1 :(得分:4)

找不到路线有两个主要原因。

1)路由被定义为传递给Navigator.of(context)的上下文 - @rmtmackenzie解释的场景

2)路线在兄弟分支上定义,例如

Root 

  -> Content (Routes e.g. Home/Profile/Basket/Search)

  -> Navigation (we want to dispatch from here)

如果我们想从Navigation小部件调度路由,我们必须知道对NavigatorState的引用。拥有全局引用非常昂贵,尤其是当您打算在树中移动窗口小部件时。 https://docs.flutter.io/flutter/widgets/GlobalKey-class.html。仅在无法从Navigator.of(上下文)获取它的地方使用它。

在MaterialApp中使用GlobalKey定义navigatorKey

final navigatorKey = GlobalKey<NavigatorState>();

Widget build(BuildContext context) => MaterialApp {
    navigatorKey: navigatorKey
    onGenerateRoute : .....
};

现在应用程序中您传递navigatorKey的任何地方都可以调用

navigatorKey.currentState.push(....);

刚发布了https://medium.com/@swav.kulinski/flutter-navigating-off-the-charts-e118562a36a5

答案 2 :(得分:1)

仅在主方法中使MaterialApp类成为该示例

 void main() => runApp(MaterialApp(home: FooClass(),));

对我来说很好, 我希望它能起作用

答案 3 :(得分:1)

确保在相同的上下文中提及路由表:

  @override
  Widget build(BuildContext context) {

    return MaterialApp(
       home: FutureBuilder(future: _isUserLoggedIn(),
                   builder: (ctx, loginSnapshot) => 
                   loginSnapshot.connectionState == ConnectionState.waiting ?
                   SplashScreen() : loginSnapshot.data == true ?  AppLandingScreen(): SignUpScreen()
                ),
       routes: {
         AppLandingScreen.routeName: (ctx) => AppLandingScreen(),
      },

    );



  }

我遇到了这个问题,因为我用不同的构建方法定义了路由表。

答案 4 :(得分:0)

关于此问题,还有另一种非常不同的解决方法,如果您使用的是警报管理器(Android),然后重新打开您的应用程序。如果导航之前尚未打开屏幕,则导航器将永远无法工作。尽管这是一种罕见的用法,但我认为这应该是一个值得了解的东西。

答案 5 :(得分:0)

是一个新手,已经花了两天的时间来克服Navigtor对象链接到黑屏的问题。

导致此问题的原因是复制的伪数据。找到贝娄两个笨拙的数据块:

**Problematic data **- duplicate assets/image:

_buildFoodItem('assets/plate1.png', 'Salmon bowl', '\$24'),
_buildFoodItem('assets/plate2.png', 'Spring bowl', '\$13'),
_buildFoodItem('assets/plate1.png', 'Salmon bowl', '\$24'),
_buildFoodItem('assets/plate5.png', 'Berry bowl', '\$34'),

**Solution **- after eliminating duplicated image argument:
_buildFoodItem('assets/plate1.png', 'Salmon bowl', '\$24'),
_buildFoodItem('assets/plate2.png', 'Spring bowl', '\$13'),
_buildFoodItem('assets/plate6.png', 'Avocado bowl', '\$34'),

我希望这可以帮助某人、、、、、

答案 6 :(得分:-1)

如果导航器不工作,可能有多种原因,但主要的一个是导航器没有找到上下文。 因此,要解决此问题,请尝试将您的小部件包装在 Builder 中,因为构建器有自己的上下文...