在 widget 树中获取State对象

220 阅读1分钟

我们有两种方法在子 widget 树中获取父级 StatefulWidget 的State 对象:

1、通过Context获取

context对象有一个findAncestorStateOfType()方法,该方法可以从当前节点沿着 widget 树向上查找指定类型的 StatefulWidget 对应的 State 对象。比如下面一段例子:

...
return LayoutBuilder(
      builder: (context, constraints) {
          return Scaffold(
              appBar: AppBar(
                title: Text("Context测试"),
              ),
              body: Row(
                children: [
                  SizedBox(
                     width: 100,
                     height: 30,
                  ),
                  Expanded(
                    child: Container(
                        padding: const EdgeInsets.all(30),
                        color: Colors.red,
                        child: Container(
                          padding: const EdgeInsets.all(3),
                          color:Theme.of(context).colorScheme.primaryContainer,
                          child: page,
                        ),
                     ),
                  ),
                ],
             ),
         );
     }
);
...

Widget build(BuildContext context) {
    Scaffold? scaffold = context.findAncestorWidgetOfExactType<Scaffold>();
    // 直接返回 AppBar的title, 此处实际上是Text("Context测试")
    if (scaffold != null && scaffold.appBar != null) {
       print((scaffold.appBar as AppBar).title);
    }
    
    //Scaffold提供了一个直接通过of静态方法来获取ScaffoldState
    ScaffoldState _state=Scaffold.of(context);

    // 注意此处找到的是向上离得最近的一个Container 
    Container? row = context.findAncestorWidgetOfExactType<Container>();
    print(row);
}
  

2、通过GlobalKey

1、给目标StatefulWidget添加GlobalKey

//定义一个globalKey, 由于GlobalKey要保持全局唯一性,我们使用静态变量存储
static GlobalKey<ScaffoldState> _globalKey= GlobalKey();
...
Scaffold(
    key: _globalKey , //设置key
    ...  
)

2、通过GlobalKey来获取State对象

_globalKey.currentState

注意:使用 GlobalKey 开销较大,尽量用其他方案。同一个 GlobalKey 在整个 widget 树中必须是唯一的,不能重复(查找资料显示必须唯一,但实际开发中貌似没有出现问题,但尽量避免同名吧)