「这是我参与11月更文挑战的第17天,活动详情查看:2021最后一次更文挑战」。
在前几篇基本简单的梳理了main.dart里面有些比较重要的一些知道点。。我们知道了runApp()
里面的一些简单的流程以及运行机制。我们也知道了StatelessWidget
、StatefulWidget
的一些简单知识点,以及知道在widget树中BuildContext
用来横穿上下文。我们在里面有提到了一个重要的知识点InheritedWidget
。今天我们就来了解一下InheritedWidget
吧。
什么是 InheritedWidget
InheritedWidget 只是一个简单的widget。他是是不可变的,除了保存data什么都不做。如果我们刷新它,就需要重建它。InheritedWidget将数据从祖先widget传递给可能位于widget树深处的后代widget。
const InheritedWidget({Key? key, required Widget child }) : super(key: key, child: child);
复制代码
Flutter 自身的InheritedWidget的widget:
Theme.of(context).textTheme
MediaQuery.of(context).size
复制代码
有一个名为 of()
的特殊方法,它可以访问其 Widget 树中任何位置的属性。
当实例化一个InheritedWidget,然后调用context.inheritedWidgetOfExactType
(或of
)时;这意味着它会侦听Element
与您的InheritedWidget
。 每当Element
获得一个新的widget时,它将强制刷新 调用前一个方法的widget。当您用InheritedWidget
全新的替换现有的时,系统会并将通知绑定的widget进行修改。
实际使用
首先,创建您自己的类来扩展 InheritedWidget 以在项目中传递数据。
class ColorInfo extends InheritedWidget {
ColorInfo({Key? key, required this.child}) : super(key: key, child: child);
final Widget child;
static ColorInfo? of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<Name>();
}
@override
bool updateShouldNotify(ColorInfo oldWidget) {
return true;
}
}
复制代码
of
方法是InheritedWidget从子widget更轻松地访问您的数据的一个约定。 updateShouldNotify
方法是告诉我们是否应该在数据更改时重新绘制依赖于数据的widget,oldwidget
参数允许您将 InheritedWidget 中的先前数据与新数据进行比较。
inheritFromWidgetOfExactType
@override
InheritedWidget inheritFromWidgetOfExactType(Type targetType, { Object aspect }) {
///在共享 map _inheritedWidgets 中查找
final InheritedElement ancestor = _inheritedWidgets == null ? null : _inheritedWidgets[targetType];
if (ancestor != null) {
///返回找到的 InheritedWidget ,同时添加当前 element 处理
return inheritFromElement(ancestor, aspect: aspect);
}
_hadUnsatisfiedDependencies = true;
return null;
}
@override
InheritedWidget inheritFromElement(InheritedElement ancestor, { Object aspect }) {
_dependencies ??= HashSet<InheritedElement>();
_dependencies.add(ancestor);
///就是将当前 element(this) 添加到 _dependents 里
///也就是 InheritedElement 的 _dependents
///_dependents[dependent] = value;
ancestor.updateDependencies(this, aspect);
return ancestor.widget;
}
@override
void notifyClients(InheritedWidget oldWidget) {
for (Element dependent in _dependents.keys) {
notifyDependent(oldWidget, dependent);
}
}
复制代码
- 在共享 map
_inheritedWidgets
中查找,如果找到,添加inheritFromElement
处理,然后返回找到的InheritedWidget
, - 将当前的
Element
加入到InheritedElement
的_dependents
这个map里面。并且交由updateDependencies
去处理,在Widget
中返回InheritedElement
。
创建一个新的 InheritedWidget 会重建整个树吗?
不一定。因为您的新 InheritedWidget 可能具有与以前完全相同的子widget(同一个实例)。拥有与之前相同实例的widget不会重建。