实质
/// [BuildContext] objects are actually [Element] objects. The [BuildContext]
/// interface is used to discourage direct manipulation of [Element] objects.
这是Flutter
sdk中介绍的英文,具体说的是BuildContext
是一个Element
的对象,并且不要直接操作这个Element
对象。
笔者在开发的时候,用的最多的就是BuildContext
,但一直不理解这个是什么东西,刚开始理解的时候就理解成“上下文”。
setState
这个回调函数初学者用的最多了,目的是数据改变需要刷新页面。
底部代码实现:
void setState(VoidCallback fn) {
...
_element!.markNeedsBuild();
}
markNeedsBuild
就是刷新页面的作用,当然如果用context
达到同样的效果,需要这样:
(context as Element).markNeedsBuild();
context参数
方法
(context as Element).findAncestorStateOfType()
(context as Element).dependOnInheritedWidgetOfExactType()
findAncestorStateOfType
:指的是当前Element
往父节点找,找到某种类型为止。
T? findAncestorStateOfType<T extends State<StatefulWidget>>() {
assert(_debugCheckStateIsActiveForAncestorLookup());
Element? ancestor = _parent;
while (ancestor != null) {
if (ancestor is StatefulElement && ancestor.state is T)
break;
ancestor = ancestor._parent;
}
final StatefulElement? statefulAncestor = ancestor as StatefulElement?;
return statefulAncestor?.state as T?;
}
具体的可以看if
语句中。dependOnInheritedWidgetOfExactType
:指的是以自己为节点离我最近的Widget
中某个特定类型查找。
T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({Object? aspect}) {
assert(_debugCheckStateIsActiveForAncestorLookup());
final InheritedElement? ancestor = _inheritedWidgets == null ? null : _inheritedWidgets![T];
if (ancestor != null) {
return dependOnInheritedElement(ancestor, aspect: aspect) as T;
}
_hadUnsatisfiedDependencies = true;
return null;
}
用例
Theme.of(context).textTheme;
var screenWidth = MediaQuery.of(context).size.width;
当然这里面直接传context
参数,而Theme``MediaQuery
可以理解成“单例”或是“类对象”,直接通过点语法调用“类方法”,而这些类对象的生成在void main() async
由系统底层生成了。
底部实现
用例中的of
方法中可以看到:
static MediaQueryData of(BuildContext context) {
assert(context != null);
assert(debugCheckHasMediaQuery(context));
return context.dependOnInheritedWidgetOfExactType<MediaQuery>()!.data;
}
这里会发现上面说到的方法dependOnInheritedWidgetOfExactType
,就是去查找离当前节点最近的MediaQuery
节点,然后返回这个Widget
节点信息。
context子节点处理
每个组件都会有自己的context
,当需要查找context的上层的某个Widget
节点的时候,则需要context
的“降级处理”。
LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
//通过子节点context去查找父组件
return Container();
},
)
总结
通过这些,就可以大致的了解了什么是BuildContext
,其实就是一个Widget
。