📌 什么是 InheritedWidget
InheritedWidget
是 Flutter 数据向下传递 的机制。- 它允许你把 数据存储在 Widget 树的某个节点,树下的子组件可以直接获取这些数据,而不需要层层参数传递。
- Flutter 的 Provider、Bloc、Theme.of、MediaQuery.of 都是基于
InheritedWidget
实现的。
📖 继承关系
plaintext
Object
↳ Diagnosticable
↳ DiagnosticableTree
↳ Widget
↳ ProxyWidget
↳ InheritedWidget
🛠 使用方式
1. 定义一个 InheritedWidget
dart
class CounterInheritedWidget extends InheritedWidget {
final int counter;
const CounterInheritedWidget({
Key? key,
required this.counter,
required Widget child,
}) : super(key: key, child: child);
// 提供一个静态方法,方便子树获取数据
static CounterInheritedWidget? of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<CounterInheritedWidget>();
}
// 当 counter 改变时,是否通知子 Widget 重新 build
@override
bool updateShouldNotify(CounterInheritedWidget oldWidget) {
return oldWidget.counter != counter;
}
}
2. 在 Widget 树中使用
dart
class CounterApp extends StatefulWidget {
@override
_CounterAppState createState() => _CounterAppState();
}
class _CounterAppState extends State<CounterApp> {
int _counter = 0;
void _increment() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return CounterInheritedWidget(
counter: _counter,
child: Scaffold(
appBar: AppBar(title: Text("InheritedWidget Demo")),
body: Center(child: CounterText()),
floatingActionButton: FloatingActionButton(
onPressed: _increment,
child: Icon(Icons.add),
),
),
);
}
}
class CounterText extends StatelessWidget {
@override
Widget build(BuildContext context) {
final inherited = CounterInheritedWidget.of(context);
return Text(
"当前计数: ${inherited?.counter}",
style: TextStyle(fontSize: 24),
);
}
}
🔍 核心点
-
数据存放在
InheritedWidget
中- 比如
counter
。
- 比如
-
子 Widget 获取数据时要用
dependOnInheritedWidgetOfExactType
- 这样,当
InheritedWidget
更新时,子 Widget 会自动build
。
- 这样,当
-
updateShouldNotify
控制是否通知- 如果返回
true
,依赖它的子 Widget 会重建。 - 如果返回
false
,不会触发更新(提高性能)。
- 如果返回
📌 实际应用
-
Flutter 内置:
Theme.of(context)
→ 通过InheritedWidget
获取主题MediaQuery.of(context)
→ 获取屏幕信息Localizations.of(context)
→ 获取国际化
-
第三方库:
Provider
、Riverpod
、Bloc
等,都是对InheritedWidget
的封装
✅ 总结
InheritedWidget
是 数据共享的基石,可以避免参数层层传递。- 适合做 全局状态(主题、语言、屏幕信息) 或 局部状态共享(比如父传子、兄弟组件共享数据)。
- 在实际项目中,我们很少直接用它,而是通过 Provider / Riverpod / Bloc 等更高级的封装。