InheritedElement 的理解与学习

96 阅读1分钟

1 调用 BuildContext.dependOnInheritedWidgetOfExactType 查找离当前节点最近的InheritedWidget

T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({ Object? aspect })

2 在Element中的实现如下 _inheritedElements , _inheritedElements 存储的是从根节点一直到当前节点所有类型的 InheritedElement。

PersistentHashMap<Type, InheritedElement>? _inheritedElements;
@override
T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({Object? aspect}) {
  assert(_debugCheckStateIsActiveForAncestorLookup());
  final InheritedElement? ancestor = _inheritedElements == null ? null : _inheritedElements![T];
  if (ancestor != null) {
    return dependOnInheritedElement(ancestor, aspect: aspect) as T;
  }
  _hadUnsatisfiedDependencies = true;
  return null;
}

3 找到指定类型的 InheritedElement,调用当前节点的dependOnInheritedElement

dependOnInheritedElement(ancestor, aspect: aspect)

3.1 第一个参数ancestor为找到的第一个指定的 InheritedWidget 3.2 aspect 一般为null

4 Element dependOnInheritedElement 实现如下

@override
InheritedWidget dependOnInheritedElement(InheritedElement ancestor, { Object? aspect }) {
  _dependencies ??= HashSet<InheritedElement>();
  _dependencies!.add(ancestor);
  ancestor.updateDependencies(this, aspect);
  return ancestor.widget as InheritedWidget;
}

4.1 _dependencies 为当前节点持有的一个set集合。换句话说就是当前节点会通过 _dependencies 存储跟自己有关系的 InheritedElement。

5 调用 InheritedElement.updateDependencies() 直接调用setDependencies 没有使用第二个参数

@protected
void updateDependencies(Element dependent, Object? aspect) {
  setDependencies(dependent, null);
}

6 这里调用的是 ancestor(InheritedElement) 的setDependencies

final Map<Element, Object?> _dependents = HashMap<Element, Object?>();
@protected
void setDependencies(Element dependent, Object? value) {
  _dependents[dependent] = value;
}

6.1 dependent就是当前的节点。value在 InheritedElement 中是null。

至此,当前节点中通过_dependencies 持有依赖的节点。Element中_dependents的keys 就是依赖自己的所有子节点。

7 刷新 回走 InheritedElement notifyClients

@override
void notifyClients(InheritedWidget oldWidget) {
  assert(_debugCheckOwnerBuildTargetExists('notifyClients'));
  for (final Element dependent in _dependents.keys) {
    assert(() {
      // check that it really is our descendant
      Element? ancestor = dependent._parent;
      while (ancestor != this && ancestor != null) {
        ancestor = ancestor._parent;
      }
      return ancestor == this;
    }());
    // check that it really depends on us
    assert(dependent._dependencies!.contains(this));
    notifyDependent(oldWidget, dependent);
  }
}

_dependents.keys 存储的就是所有依赖当前InheritedElement 的子节点

7.1 调用 notifyDependent,最终调用所有依赖当前节点的子节点的 didChangeDependencies

@protected
void notifyDependent(covariant InheritedWidget oldWidget, Element dependent) {
  dependent.didChangeDependencies();
}

InheritedModel 与 SharedAppData 基于InheritedElement实现的更细粒度的刷新跟数据共享。