InheritedWidget 是 Flutter 中数据共享和状态传播的底层机制,也是 Provider、Riverpod 等状态管理方案的基石。
一、什么是 InheritedWidget
InheritedWidget 是一种特殊的 Widget,它可以让子树中的 Widget 高效地获取共享数据 ,并在数据变化时自动重建依赖它的 Widget。
// 简单示例
class MyInheritedWidget extends InheritedWidget {
final int data;
const MyInheritedWidget({
required this.data,
required Widget child,
}) : super(child: child);
@override
bool updateShouldNotify(MyInheritedWidget oldWidget) {
return data != oldWidget.data; // 数据变化时通知
}
static MyInheritedWidget? of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
}
}
二、核心原理
1. 整体架构

2. 核心数据结构
// InheritedElement 的核心数据结构
class InheritedElement extends ProxyElement {
// 依赖映射表:key 是依赖的 Element,value 是依赖的数据
final Map<Element, Object?> _dependents = HashMap<Element, Object?>();
// 通知所有依赖者数据已变化
void notifyClients(InheritedWidget oldWidget) {
for (final dependent in _dependents.keys) {
notifyDependent(oldWidget, dependent);
}
}
// 通知单个依赖者
void notifyDependent(covariant InheritedWidget oldWidget, Element dependent) {
dependent.didChangeDependencies(); // 触发依赖者重建
}
}
3. 依赖注册过程
// Element 中的依赖注册方法
Element {
Map<Type, InheritedElement>? _dependencies;
void _registerDependency(InheritedElement ancestor) {
_dependencies ??= HashMap<Type, InheritedElement>();
_dependencies![ancestor.widget.runtimeType] = ancestor;
ancestor.updateDependencies(this, null); // 在 InheritedElement 中注册
}
// 获取最近的指定类型的 InheritedWidget
T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>() {
final ancestor = _getClosestAncestorOfType(T);
if (ancestor != null) {
_registerDependency(ancestor); // 注册依赖
return ancestor.widget as T;
}
return null;
}
}
三、核心原理
-
依赖注册 :子 Widget 调用
dependOnInheritedWidgetOfExactType时,会在 InheritedElement 中注册 -
变化通知 :数据变化时,InheritedElement 遍历
_dependents调用didChangeDependencies -
自动重建:依赖的 Element 收到通知后标记为 dirty,下一帧重建
关键点
-
updateShouldNotify决定是否通知 -
dependOnInheritedWidgetOfExactType注册依赖 -
使用
const和缓存优化性能 -
适合少量、全局的共享数据
四、InheritedWidget 获取原理
MyInheritedWidget.of(context) 的核心原理是向上遍历 Element 树 并建立依赖关系。
核心调用链
MyInheritedWidget.of(context)
// 实际调用
static MyInheritedWidget of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
}
五、dependOnInheritedWidgetOfExactType 源码分析
1. Element 中的实现
// Element 类中的核心方法
abstract class Element implements BuildContext {
@override
T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({Object? aspect}) {
// 步骤1: 获取最近的指定类型的 InheritedElement
final InheritedElement ancestor = _getInheritedOfExactType<T>();
if (ancestor != null) {
// 步骤2: 注册依赖关系
return dependOnInheritedElement(ancestor, aspect) as T;
}
// 步骤3: 没找到时触发错误
_hadUnsatisfiedDependencies = true;
return null;
}
// 获取最近的 InheritedElement
InheritedElement? _getInheritedOfExactType<T extends InheritedElement>() {
// 从当前 Element 开始向上遍历
Element? ancestor = _parent;
while (ancestor != null) {
if (ancestor is InheritedElement && ancestor.widget is T) {
return ancestor; // 找到了!
}
ancestor = ancestor._parent;
}
return null;
}
// 建立依赖关系
@override
T dependOnInheritedElement<T extends InheritedElement>(InheritedElement ancestor, {Object? aspect}) {
// 注册依赖:将当前 Element 添加到 ancestor 的依赖表中
ancestor.updateDependencies(this, aspect);
// 返回 InheritedWidget 实例
return ancestor.widget as T;
}
}
2. InheritedElement 中的依赖管理
class InheritedElement extends ProxyElement {
// 依赖表:key 是依赖的 Element,value 是依赖的方面
final Map<Element, Object?> _dependents = HashMap<Element, Object?>();
// 更新依赖关系
void updateDependencies(Element dependent, Object? aspect) {
// 将当前 Element 加入依赖表
_dependents[dependent] = aspect;
}
// 通知所有依赖者
void notifyClients(InheritedWidget oldWidget) {
for (final Element dependent in _dependents.keys) {
notifyDependent(oldWidget, dependent);
}
}
// 通知单个依赖者
void notifyDependent(InheritedWidget oldWidget, Element dependent) {
dependent.didChangeDependencies();
}
}
六、完整流程图

七、源码实现
1. 向上查找的完整过程
// Element 的 _parent 是如何建立的
class Element {
Element? _parent;
void mount(Element? parent, dynamic newSlot) {
_parent = parent; // 挂载时设置父节点
_depth = _parent != null ? _parent!.depth + 1 : 1;
// ...
}
}
// 查找过程的详细实现
InheritedElement? _getInheritedOfExactType<T extends InheritedElement>() {
// 从当前 Element 开始
Element? ancestor = this;
// 向上遍历直到根节点
while (ancestor != null) {
// 检查是否是指定类型
if (ancestor is InheritedElement && ancestor.widget is T) {
return ancestor;
}
// 继续向上
ancestor = ancestor._parent;
}
return null;
}
关键点:
-
匹配的是
ancestor.widget is T(类型检查) -
不比较实例是否相同
-
不比较数据内容
2. 依赖表的内部结构
// 模拟依赖表的结构
class InheritedElement {
// 依赖表示例
// _dependents = {
// element1: null, // 依赖整个 Widget
// element2: 'count', // 依赖特定方面
// element3: null, // 依赖整个 Widget
// }
final Map<Element, Object?> _dependents = {};
void updateDependencies(Element dependent, Object? aspect) {
// 如果已存在,更新 aspect
// 如果不存在,添加新条目
_dependents[dependent] = aspect;
}
// 选择性通知(根据 aspect)
void notifyClients(InheritedWidget oldWidget) {
for (final entry in _dependents.entries) {
if (shouldNotify(entry.key, entry.value)) {
entry.key.didChangeDependencies();
}
}
}
}