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),
);
}
}

核心点

  1. 数据存放在 InheritedWidget

    • 比如 counter
  2. 子 Widget 获取数据时要用 dependOnInheritedWidgetOfExactType

    • 这样,当 InheritedWidget 更新时,子 Widget 会自动 build
  3. updateShouldNotify 控制是否通知

    • 如果返回 true,依赖它的子 Widget 会重建。
    • 如果返回 false,不会触发更新(提高性能)。

实际应用

  • Flutter 内置

    • Theme.of(context) → 通过 InheritedWidget 获取主题
    • MediaQuery.of(context) → 获取屏幕信息
    • Localizations.of(context) → 获取国际化
  • 第三方库

    • ProviderRiverpodBloc 等,都是对 InheritedWidget 的封装

✅ 总结

  • InheritedWidget数据共享的基石,可以避免参数层层传递。
  • 适合做 全局状态(主题、语言、屏幕信息)局部状态共享(比如父传子、兄弟组件共享数据)
  • 在实际项目中,我们很少直接用它,而是通过 Provider / Riverpod / Bloc 等更高级的封装。
posted @ 2025-08-25 18:24  wzzkaifa  阅读(21)  评论(0)    收藏  举报