【问题标题】:Flutter showDialog(context) in initState method在 initState 方法中颤振 showDialog(context)
【发布时间】:2019-01-16 21:59:51
【问题描述】:

我正在尝试使用showDialog(context, builder) 在用户导航到某个页面时显示问候消息。

我通过在该页面上的有状态小部件的initState 方法中调用showDialog 来尝试此操作。虽然它确实有效,但似乎我无法访问实际上下文。

Flutter 中有没有办法在initState() 方法中访问context

如果没有,是否有其他方法可以更好地实现此行为?

@override
void initState() {
  super.initState();
  new Future.delayed(Duration.zero, () {
    showDialog(context: context, 
    builder: (BuildContext context) {
      return new Container(child: new Text('foo'));
    });
  });
}

【问题讨论】:

  • 您可以在initState 方法中访问context。而且您链接的代码确实有效
  • “虽然它确实有效,但我似乎无法访问实际的上下文。”.. 你是怎么说的?
  • 也许我误解了这个问题,我的小部件没有应用主题,而且这段代码看起来很可怕,也许上下文在那里,但我必须为上下文获取主题或什么?我回家后会检查一下。
  • 次要,但您可能不需要Container

标签: flutter


【解决方案1】:

对于新手,您可以像其他人所说的那样访问 initState 中的上下文。 initState 构建函数中唯一的问题尚未执行。所以这个上下文有点空。

要解决这个问题,你可以使用SchedulerBinding

SchedulerBinding.instance.addPostFrameCallback((_) => doSomethingNextFrame(context));

addPostFrameCallback:在此帧结束时安排回调。

Future.delayed(Duration.zero) 也可以。但我认为 SchedulerBinding 看起来更干净。

【讨论】:

    【解决方案2】:

    虽然这肯定不是最流畅的方式,但您可以创建一个函数,在所有内容都已构建后,在短时间内显示对话框。它看起来像这样:

    void initState() {
        super.initState();
        _showDialog();
      }
    
    _showDialog() async {
        await Future.delayed(Duration(milliseconds: 50));
        showDialog(
            context: context,
            builder: (BuildContext context) {
              return new Container(child: new Text('foo'));
            });
      }
    

    【讨论】:

    • @SebastianRoth 我对此并不完全确定,但我读过 initState() 方法中调用的异步调用或 Future 会延迟到 initState() 调用之后。 Dart VM/Flutter 引擎就是这样做的。因此,您甚至可以省略 Future.delayed() 调用,只是推测,未经测试。
    【解决方案3】:
    @override
      void initState() {
        super.initState();
        WidgetsBinding.instance.addPostFrameCallback((_) async {
          await showDialog<String>(
            context: context,
            builder: (BuildContext context) => new showDialog(
               context: context, 
               builder: (BuildContext context) {
                  return new Container(child: new Text('foo'));
              });
          );
        });
      }
    

    【讨论】:

      【解决方案4】:

      你有正确的context。但是您应该使用一些Dialog 小部件来获得正确的对话框。

      showDialog(context: context, builder: (context) {
         return new SimpleDialog(children: <Widget>[new Center(child: new Container(child: new Text('foo')))]);
      });
      

      您可以找到更多对话框小部件herehere

      【讨论】:

        【解决方案5】:

        这项工作使用方法构建小部件中的键。

        首先创建密钥:

          final GlobalKey<NavigatorState> key =
          new GlobalKey<NavigatorState>();
        

        与我们的小部件绑定后:

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

        最后我们使用key调用.currentContext参数。

            @override
              void initState() {
                super.initState();
                SchedulerBinding.instance.addPostFrameCallback((_) {
                    // your method where use the context
                    // Example navigate:
                    showDialog(key.currentContext); 
                });
           }
        

        编码愉快。

        【讨论】:

          猜你喜欢
          • 2020-01-10
          • 1970-01-01
          • 2020-02-25
          • 2020-06-07
          • 2022-10-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-10-14
          相关资源
          最近更新 更多