以下断言被引发构建导航器

时间:2020-01-19 13:46:20

标签: flutter dart

构建第一个小部件时可以导航到另一个小部件吗?

在构建Navigator- [GlobalObjectKey _WidgetsAppState#1d8fb](脏,状态:NavigatorState#999bc(股票代码:跟踪2个股票))时引发了以下断言:

im试图演示如何在不按任何按钮的情况下从一个屏幕导航到另一个屏幕,我的意思是,如果im在某个屏幕上,它将在几秒钟后不执行任何操作的情况下加载另一个屏幕,但是当我将导航器放在外面时构建方法并使用initState调用它,这给了我一个错误。 这是我的代码

 class Screen0 extends StatefulWidget {
  @override
  _Screen0State createState() => _Screen0State();
}

class _Screen0State extends State<Screen0> {
  @override
  void initState() {
    changeScreen();
    super.initState();
  }

  void changeScreen() {
    Navigator.push(context, MaterialPageRoute(builder: (context) {
      return MyHomePage(title: 'Flutter Demo Home Page');
    }));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold();
  }
}


--------------------- my other screen -----------------------------
import 'package:flutter/material.dart';

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

我使用了changeScreen方法中导航器的以下代码对其进行了修复:

Future(() {
        Navigator.push(
            context, MaterialPageRoute(builder: (context) => CityScreen()));
      });

谢谢大家的帮助!

2 个答案:

答案 0 :(得分:2)

您需要更多地了解Flutter中小部件的生命周期。调用initState时,框架正忙于将窗口小部件渲染到窗口小部件树。它在initState中所做的全部工作就是收集其以某种方式呈现小部件所需的信息。

通过在initState中调用changeScreen()来执行的操作是,告诉flutter在已经构建了另一个小部件时就对其进行构建。这会导致错误。

只有在构建第一个窗口小部件时,您才能导航到(或构建)另一个窗口小部件。

现在让我们谈谈如何完成自己想做的事情。

构建主屏幕后,您想在不到一秒钟的时间内导航到另一个小部件。

您需要让flutter渲染其主窗口小部件(您要编辑其initState),然后才告诉它导航至另一个窗口小部件。

像这样更改您的changeScreen()函数:

  changeRoute() async {
    await Future.delayed(Duration(seconds: 1), () {
      Navigator.push(
        context,
        MaterialPageRoute(builder: (context) => SecondRoute()),
      );
    });
  }

这里发生的事情是,事件循环等待1秒钟(由我们在Future.delayed方法中定义),然后changeScreen()中的所有事情都会发生。在那一秒钟的末尾,flutter渲染其主窗口小部件并查找剩余的内容。还剩啥?我们的changeScreen()

因此,一秒钟后。屏幕导航。

PS:这个答案可能值得商as,因为我们不知道要花多少时间才能渲染主窗口小部件。如果要花费一秒钟以上的时间(非常罕见),则该错误将继续存在。

答案 1 :(得分:0)

 import 'package:flutter/material.dart';
 main()=>runApp(MyApp());

 class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'MyApp',
      initialRoute: '/',
      routes: {
        '/': (context) => Screen0(),
        '/home': (context) => MyHomePage(),
      },
    );
  }
}

 class Screen0 extends StatefulWidget {
  @override
  _Screen0State createState() => _Screen0State();
}

class _Screen0State extends State<Screen0> {
  @override
  void initState() {
    changeScreen();
    super.initState();
  }

  void changeScreen() {
      // The delay fixes it
    Future.delayed(Duration(milliseconds: 5000)).then((_) {
      Navigator.pushReplacementNamed(context, '/home');
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
    body: Center(
      child: Text('First Screen'),
    ),
    );
  }
}


class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(''),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

检查一下,它可能会帮助您。

让我知道它是否有效

谢谢。