zoukankan      html  css  js  c++  java
  • 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,所以不会报错。

  • 相关阅读:
    HttpWebRequest中的ContentType详解
    c# 创建Windows服务
    转载 Url编码
    在应用程序级别之外使用注册为 allowDefinition='MachineToApplication' 的节是错误的。
    IE兼容模式下 SCRIPT1028: 缺少标识符、字符串或数字
    Response.ContentLength获取文件大小
    unable to instantiate activity...
    查看android-support-v4.jar引出的问题
    导入项目 R.java没有
    初识python: 局部变量、全局变量
  • 原文地址:https://www.cnblogs.com/FdWzy/p/13515228.html
Copyright © 2011-2022 走看看