• flutter context踩坑


    下面代码有三个button,内容都是一样的,只不过包装方式不同。

    第一个是没有包装的,第二个用Builder包了一层,第三个封装成了StatelessWidget。

    运行一下,第一个button会报如下错误:

    是说调用的Scaffod.of(context)找不到Scaffold。

    import 'package:flutter/material.dart';
    
    void main() => runApp(BuilderApp());
    
    class BuilderApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: BuilderHomePage(),
        );
      }
    }
    
    class BuilderHomePage extends StatefulWidget {
      @override
      _BuilderHomePageState createState() => _BuilderHomePageState();
    }
    
    class _BuilderHomePageState extends State<BuilderHomePage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text("Hello"),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                RaisedButton(
                  onPressed: () {
                    Scaffold.of(context).showSnackBar(
                        new SnackBar(content: Text("Hello  SnackBar1")));
                  },
                  child: Text("Test"),
                ),
                Builder(
                  builder: (BuildContext context) {
                    return RaisedButton(
                      onPressed: () {
                        Scaffold.of(context).showSnackBar(
                            new SnackBar(content: Text("Hello  SnackBar2")));
                      },
                      child: Text("Builder SnackBar"),
                    );
                  },
                ),
                WidgetTest()
              ],
            ),
          ),
        );
      }
    }
    
    
    class WidgetTest extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Container(
          child:     RaisedButton(
            onPressed: () {
              Scaffold.of(context).showSnackBar(
                  new SnackBar(content: Text("Hello  SnackBar3")));
            },
            child: Text("No Builder SnackBar"),
          ),
        );
      }
    }

    分析一下:

    这是Scaffold.of(context)的源码

    可以看到这个方法返回的是findAncestorStateOfType()。其实所有.of(context).xxx这样的方法都是调用这个东西。

    点进去看看:

    可以看到这个方法是在依次向上遍历该widget的祖先,直到找到一个符合参数类型的祖先就退出。

    注意最开始赋值是把当前widget的_parent赋给了ancestor,所以是从当前widget的父节点开始找的。

    那么就很容易判断了:

    第一个button的context复用了build函数的context(android studio很贴心的会高亮两个context的连接关系) 

    第二个button用Builder套了一层,它的context是Builder的builder函数的参数context

     第三个button的context是StatelessWidget的build函数参数的context,就不截图了。

    由于第一个button的context和scaffold是同一个,所以从它的_parent往上找肯定找不到scaffold,所以报错。

    另外两个button都是scaffold的子节点,他俩的_parent恰好就是scaffold,所以不会报错。

  • 相关阅读:
    golang中os/user包用法
    golang中os包用法
    与table有关的布局
    jQuery 从 1.9 版开始,移除了 $.browser 和 $.browser.version
    canvas里调用getImageData的报security的问题
    CSS样式覆盖规则
    windows7文件夹怎样默认图片大图显示?
    Jboss,Tomcat 远程调试配置
    IE(IE6/IE7/IE8)支持HTML5标签
    JS 继承(类式 与 原型式)
  • 原文地址:https://www.cnblogs.com/FdWzy/p/13515228.html
Copyright © 2020-2023  润新知