Flutter BuildContext
Element通过接口实现了BuildContext,BuildContext会暴露少量方法和对象给开发者用来获取Element相关的信息.如果把整个element暴露给开发者容易对组件造成污染,例如各种生命周期方法或更新操作.下面是一些BuildContext提供给开发者使用的方法(不包含已废弃的方法,已废弃的方法基本都有通过泛型实现相同功能的方法).
dependOnInheritedElement
通过传入的InheritedElement获取相应的InheritedWidget,并会添加当前element到InheritedElement的_dependents,如果InheritedElement发生更新会触发当前element的更新.
InheritedWidget dependOnInheritedElement(InheritedElement ancestor, { Object aspect });
dependOnInheritedWidgetOfExactType
通过传入的InheritedWidget泛型获取相应的InheritedElement,然后通过上面的dependOnInheritedElement返回相应的InheritedWidget对象.
这个方法会绑定组件和InheritedWidget之前的关系,如果InheritedWidget组件发生了更新会触发这个组件的rebuild.
T dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({Object aspect});
这个方法用的地方挺多的,比如我们常用的Theme.of(context)用的就是这个方法.
Demo:
class Theme{
static ThemeData of(BuildContext context, { bool shadowThemeOnly = false }) {
final _InheritedTheme inheritedTheme = context.dependOnInheritedWidgetOfExactType<_InheritedTheme>();
...
}
至于怎么通过InheritedWidget泛型获取相应的InheritedWidget对象可以看一下InheritedWidget的实现原理.
getElementForInheritedWidgetOfExactType
通过InheritedWidget的泛型T拿到它的Element,它和dependOnInheritedWidgetOfExactType的区别就是是否会在两个widget之间创建绑定关系
它不会绑定调用组件和InheritedWidget组件之间的联系,也就是InheritedWidget组件改变的时候并不会触发更新调用这个方法所在的widget.
InheritedElement getElementForInheritedWidgetOfExactType<T extends InheritedWidget>();
findAncestorWidgetOfExactType
通过递归element._parent拿到element.widget.runtimeType == T的widget
T findAncestorWidgetOfExactType<T extends Widget>();
可以看一下Element对它的实现代码
@override
T findAncestorWidgetOfExactType<T extends Widget>() {
///拿到父element
Element ancestor = _parent;
///如果父element不为null,并且父element的widget的runtimeType != 泛型T
while (ancestor != null && ancestor.widget.runtimeType != T)
//递归查找父element
ancestor = ancestor._parent;
return ancestor?.widget as T;
}
findAncestorStateOfType
通过传入的泛型T向上递归获取element的state类型为T的state,它的实现代码和上面的差不多,只不过换了循环的判断逻辑.
T findAncestorStateOfType<T extends State>();
看一下实现代码
@override
T findAncestorStateOfType<T extends State<StatefulWidget>>() {
Element ancestor = _parent;
while (ancestor != null) {
///满足条件就停止循环,返回第一个满足条件的祖先element的state
if (ancestor is StatefulElement && ancestor.state is T)
break;
ancestor = ancestor._parent;
}
final StatefulElement statefulAncestor = ancestor as StatefulElement;
return statefulAncestor?.state as T;
}
findRootAncestorStateOfType
通过传入的TypeMatcher的泛型T向上递归获取element的state类型为T的state和findAncestorWidgetOfExactType的区别在一它是获取最近满足条件的parent.state而当前函数获取的最远节点的满足条件的parent.state
T findRootAncestorStateOfType<T extends State>();
看一下实现代码
@override
T findRootAncestorStateOfType<T extends State<StatefulWidget>>() {
Element ancestor = _parent;
StatefulElement statefulAncestor;
while (ancestor != null) {
///满足条件并不会停止循环,它会查询并返回最远祖先的element的State
if (ancestor is StatefulElement && ancestor.state is T)
statefulAncestor = ancestor;
ancestor = ancestor._parent;
}
return statefulAncestor?.state as T;
}
findAncestorRenderObjectOfType
通过方法的泛型获取相应的RenderObject
T findAncestorRenderObjectOfType<T extends RenderObject>();
以上就是buildContext相对常用的方法.其实我们用的最多的就是dependOnInheritedWidgetOfExactType.
完结撒花 [烟花].