InheritedWidget

95 阅读1分钟

一、InheritedWidget 定义

class ShareDataWidget extends InheritedWidget {
  ShareDataWidget({
    Key? key,
    required this.data,
    required Widget child,
  }) : super(key: key, child: child);

  final int data; //需要在子树中共享的数据,保存点击次数

  //定义一个便捷方法,方便子树中的widget获取共享数据
  static ShareDataWidget? of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<ShareDataWidget>();
  }

  //该回调决定当data发生变化时,是否通知子树中依赖data的Widget重新build
  @override
  bool updateShouldNotify(ShareDataWidget old) {
    return old.data != data;
  }
}

二、Element类中dependOnInheritedWidgetOfExactType 的实现


Map<Type, InheritedElement>? _inheritedWidgets;
Set<InheritedElement>? _dependencies;

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

@override
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;
}
InheritedElement 根节点添加子节点
void setDependencies(Element dependent, Object? value) {

_dependents[dependent] = value;

}

通过实现可以看到,调用of方法的Element---设为A(子节点),中_dependencies就是存储依赖的InheritedWidget,调用of方法就能取到InheritedWidget。同时将A节点添加到ancestor的_dependents中

结果是两个组件互相都知道。。。

当InheritedWidget 中的数据变化的时候, updateShouldNotify被调用,通知到子节点 A。子节点的didChangeDependencies被调用。

class _TestWidget extends StatefulWidget {
  @override
  __TestWidgetState createState() => __TestWidgetState();
}

class __TestWidgetState extends State<_TestWidget> {
  @override
  Widget build(BuildContext context) {
    //使用InheritedWidget中的共享数据
    return Text(ShareDataWidget.of(context)!.data.toString());
  }

  @override //下文会详细介绍。
  void didChangeDependencies() {
    super.didChangeDependencies();
    //父或祖先widget中的InheritedWidget改变(updateShouldNotify返回true)时会被调用。
    //如果build中没有依赖InheritedWidget,则此回调不会被调用。
    print("Dependencies change");
  }
}

三 最后的数据结构

WechatIMG1472.jpeg