Flutter BuildContext的常用方法

3,492 阅读2分钟

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.

完结撒花 [烟花].