InheritedWidget
InheritedWidget 是 Flutter 实现数据从上向下共享的基础机制。Provider 等状态管理方案都是基于它封装的。
基本原理
InheritedWidget 允许数据在 Widget 树中自顶向下传递,子组件可以通过 BuildContext 获取最近父级提供的 InheritedWidget 数据。当数据变化时,依赖该数据的子组件会自动重建。
手动实现示例
1. 创建 InheritedWidget
dart
class CounterData extends InheritedWidget {
const CounterData({
super.key,
required this.count,
required this.onIncrement,
required super.child,
});
final int count;
final VoidCallback onIncrement;
// 静态方法:让子组件方便获取数据
static CounterData of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<CounterData>()!;
}
// 决定是否通知依赖的子组件重建
@override
bool updateShouldNotify(CounterData oldWidget) {
return count != oldWidget.count;
}
}2. 在 Widget 树中提供数据
dart
class CounterProvider extends StatefulWidget {
final Widget child;
const CounterProvider({super.key, required this.child});
@override
State<CounterProvider> createState() => _CounterProviderState();
}
class _CounterProviderState extends State<CounterProvider> {
int _count = 0;
void _increment() {
setState(() => _count++);
}
@override
Widget build(BuildContext context) {
return CounterData(
count: _count,
onIncrement: _increment,
child: widget.child, // 子树
);
}
}3. 在子组件中使用
dart
class CounterDisplay extends StatelessWidget {
const CounterDisplay({super.key});
@override
Widget build(BuildContext context) {
final data = CounterData.of(context); // 获取数据
return Text('计数: ${data.count}');
}
}
class CounterButton extends StatelessWidget {
const CounterButton({super.key});
@override
Widget build(BuildContext context) {
final data = CounterData.of(context); // 获取方法
return ElevatedButton(
onPressed: data.onIncrement,
child: const Text('+1'),
);
}
}
// 使用
CounterProvider(
child: Scaffold(
body: Column(
children: const [
CounterDisplay(),
CounterButton(),
],
),
),
)核心方法
dependOnInheritedWidgetOfExactType
dart
// 注册依赖 —— 数据变化时会重建该组件
static CounterData of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<CounterData>()!;
}getInheritedWidgetOfExactType(不注册依赖)
dart
// 不注册依赖 —— 数据变化时不会重建(只读取一次值)
static CounterData read(BuildContext context) {
return context.getInheritedWidgetOfExactType<CounterData>()!;
}updateShouldNotify
dart
@override
bool updateShouldNotify(CounterData oldWidget) {
// 返回 true → 通知依赖的子组件重建
// 返回 false → 不通知
return count != oldWidget.count;
}实际使用建议
手写 InheritedWidget 比较繁琐。在实际项目中,推荐直接使用 Provider,它是对 InheritedWidget 的优雅封装。
TIP
理解 InheritedWidget 的原理有助于你理解 Provider 等上层框架的工作方式,但在实际开发中通常不需要手动实现。
