Flutter InheritedWidget 详解
📌 什么是 InheritedWidget
InheritedWidget
是 Flutter 数据向下传递 的机制。- 它允许你把 数据存储在 Widget 树的某个节点,树下的子组件可以直接获取这些数据,而不需要层层参数传递。
- Flutter 的 Provider、Bloc、Theme.of、MediaQuery.of 都是基于
InheritedWidget
实现的。
📖 继承关系
Object↳ Diagnosticable↳ DiagnosticableTree↳ Widget↳ ProxyWidget↳ InheritedWidget
🛠 使用方式
1. 定义一个 InheritedWidget
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 bool updateShouldNotify(CounterInheritedWidget oldWidget) {return oldWidget.counter != counter;}
}
2. 在 Widget 树中使用
class CounterApp extends StatefulWidget { _CounterAppState createState() => _CounterAppState();
}class _CounterAppState extends State<CounterApp> {int _counter = 0;void _increment() {setState(() {_counter++;});}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 {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 等更高级的封装。