相关API
- InheritedWidget
- ProxyWidget
- InheritedElement
基本用法
提供一种在widget树中从上到下共享数据的方式。当前节点和关联节点同时注册。当build时,会检查是否需要刷新。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| class InheritedWidgetTestRoute extends StatefulWidget { @override _InheritedWidgetTestRouteState createState() => _InheritedWidgetTestRouteState(); }
class _InheritedWidgetTestRouteState extends State<InheritedWidgetTestRoute> { int count = 0;
@override Widget build(BuildContext context) { return Center( child: ShareDataWidget( data: count, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Padding( padding: const EdgeInsets.only(bottom: 20.0), child: TestInheritWidget(), ), ElevatedButton( child: const Text("Increment"), onPressed: () => setState(() => ++count), ) ], ), ), ); } }
class TestInheritWidget extends StatefulWidget { @override _TestInheritWidgetState createState() => _TestInheritWidgetState(); }
class _TestInheritWidgetState extends State<TestInheritWidget> { @override Widget build(BuildContext context) { return Text(ShareDataWidget.of(context)!.data.toString()); }
@override void didChangeDependencies() { super.didChangeDependencies(); print("_TestInheritWidgetState Dependencies change"); }
@override void didUpdateWidget(covariant TestInheritWidget oldWidget) { print('_TestInheritWidgetState didUpdateWidget'); super.didUpdateWidget(oldWidget); } }
class ShareDataWidget extends InheritedWidget { ShareDataWidget({Key? key, required Widget child, required this.data}) : super(key: key, child: child);
final int data;
static ShareDataWidget? of(BuildContext context) { return context.dependOnInheritedWidgetOfExactType<ShareDataWidget>(); }
@override bool updateShouldNotify(covariant ShareDataWidget oldWidget) { return oldWidget.data != data; } }
|
核心函数
Element中,_inheritedWidgets保存了所有上级节点的InheritedElement。mounted方法会调用_updateInheritance方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| Map<Type, InheritedElement>? _inheritedWidgets;
void _updateInheritance() { assert(_lifecycleState == _ElementLifecycle.active); _inheritedWidgets = _parent?._inheritedWidgets; }
void _updateInheritance() { assert(_lifecycleState == _ElementLifecycle.active); final Map<Type, InheritedElement>? incomingWidgets = _parent?._inheritedWidgets; if (incomingWidgets != null) _inheritedWidgets = HashMap<Type, InheritedElement>.of(incomingWidgets); else _inheritedWidgets = HashMap<Type, InheritedElement>(); _inheritedWidgets![widget.runtimeType] = this; }
|
在需要使用数据的的地方,会调用dependOnInheritedWidgetOfExactType这个方法来获取相应的数据。而这个方法的Element中的实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({Object? aspect}) { final InheritedElement? ancestor = _inheritedWidgets == null ? null : _inheritedWidgets![T]; if (ancestor != null) { return dependOnInheritedElement(ancestor, aspect: aspect) as T; } _hadUnsatisfiedDependencies = true; return null; }
InheritedWidget dependOnInheritedElement(InheritedElement ancestor, { Object? aspect }) { _dependencies ??= HashSet<InheritedElement>(); _dependencies!.add(ancestor); ancestor.updateDependencies(this, aspect); return ancestor.widget as InheritedWidget; }
|
从根节点到子节点,以runtimeType作为key,保存最新的Element对象。getElementForInheritedWidgetOfExactType方法可以通过类型查找离自己最近的类型的对象。
dependOnInheritedWidgetOfExactType方法会注册依赖,当InheritedWidget发生变化时就会更新依赖它的子组件。
updated
当进行build的时候,ProxyElement这个节点会调用updated方法,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| void update(ProxyWidget newWidget) { final ProxyWidget oldWidget = widget as ProxyWidget; super.update(newWidget); updated(oldWidget); rebuild(force: true); }
void updated(InheritedWidget oldWidget) { if ((widget as InheritedWidget).updateShouldNotify(oldWidget)) { super.updated(oldWidget); } }
void updated(covariant ProxyWidget oldWidget) { notifyClients(oldWidget); }
void notifyClients(InheritedWidget oldWidget) { for (final Element dependent in _dependents.keys) { notifyDependent(oldWidget, dependent); } }
void notifyDependent(covariant InheritedWidget oldWidget, Element dependent) { dependent.didChangeDependencies(); }
|
updateShouldNotify
控制依赖于InheritedWidget的组件是否需要重建。如果为true,则当InheritedWidget发生变化时,依赖于它的组件会被rebuild,其Element的didChangeDependencies会被调用。
参考