【问题标题】:The following assertion was thrown building Navigator在构建 Navigator 时抛出了以下断言
【发布时间】:2021-12-03 13:14:48
【问题描述】:

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

The following assertion was thrown building Navigator-[GlobalObjectKey<NavigatorState> _WidgetsAppState#1d8fb](dirty, state: NavigatorState#999bc(tickers: tracking 2 tickers)):

我试图演示如何在不按任何按钮的情况下从一个屏幕导航到另一个屏幕,我的意思是如果我在某个屏幕上它会在几秒钟后加载另一个屏幕而我没有做任何事情,但是当我把导航器放在外面时build 方法并用 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()));
      });

谢谢大家的帮助!

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

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

    你在 initState 中调用changeScreen() 所做的是,你告诉颤振在它已经构建一个小部件时构建另一个小部件。这给出了一个错误。

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

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

    您希望在构建主屏幕后几分之一秒后导航到另一个小部件。

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

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

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

    这里发生的是,事件循环等待 1 秒(由我们在 Future.delayed 方法中定义),然后changeScreen() 中的所有内容都会发生。在那 1 秒结束时,flutter 渲染了它的主要小部件并寻找剩下的东西。还剩下什么?我们的changeScreen()!!

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

    PS:这个答案可能值得商榷,因为我们不知道 Flutter 渲染主小部件需要多少时间。如果超过一秒(非常罕见),则错误将持续存在。

    【讨论】:

    • 您好,非常感谢您的解释,您在这里所说的是我不久前找到的答案,并像这样修复了我的代码:void changeScreen() { Future(() { Navigator. push(context, MaterialPageRoute(builder: (context) => MyHomePage(title: 'Flutter Demo Home Page'))); }); }
    【解决方案2】:
     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),
          ),
        );
      }
    }
    

    看看这个,它可能会帮助你。

    让我知道它是否有效

    谢谢。

    【讨论】:

    • 非常感谢,我将导航器放在 Future 方法中,它工作了!
    猜你喜欢
    • 2023-02-08
    • 2021-09-09
    • 2019-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-25
    • 2019-05-15
    • 2023-01-21
    相关资源
    最近更新 更多