在同一组件树下,有时会涉及到跨组件的数据传递。
传统的方式就是利用构造函数逐级传递。过程中,也许有些层级并不需要使用,仅仅起到中转作用。这样,就会造成代码的冗余,较高的耦合性也提高了维护的成本。
/* 伪代码示意 */
return A(
data:data
child:B(
data:data
child:C(
data:data
child:D(
data:data // 真正需要使用的一层
)
)
)
)
😵 未使用InheritedWidget,运用构造函数传递
class MyWidget extends StatelessWidget {
final num = 1;
const MyWidget({super.key});
Widget build(BuildContext context) {
return Test1(num); // 构造函数传递
}
}
/* ---自定义组件Test1--- */
class Test1 extends StatelessWidget {
final int _num;
Test1(this._num, {super.key}); // 中转的无用层
Widget build(BuildContext context) {
return Container(
child: Test2(_num), // 构造函数传递
);
}
}
/* ---自定义组件Test2--- */
class Test2 extends StatelessWidget {
final int _num;
Test2(this._num, {super.key});
Widget build(BuildContext context) {
return Container(
child: Text(_num.toString()), // 需要使用数据的地方
);
}
}
为了解决以上问题,Flutter提供了InheritedWidget这样一个状态管理组件,它提供了一种在组件树中从上到下共享数据的方式,即在父widget中通过InheritedWidget共享了一个数据,那么在任意子widget都能获取该共享的数据!
😀 使用InheritedWidget
class MyWidget extends StatelessWidget {
final num = 1;
const MyWidget({super.key});
Widget build(BuildContext context) {
// InheritedWidget包裹根组件
return ShareDataWidget(
num,
child: Test1()
);
}
}
/* ---自定义组件Test1,Test2--- */
class Test1 extends StatelessWidget {
Test1({super.key});
Widget build(BuildContext context) {
return Container(
child: Test2(),
);
}
}
class Test2 extends StatelessWidget {
Test2({super.key});
Widget build(BuildContext context) {
return Container(
// 通过状态管理组件直接获取数据
child: Text(ShareDataWidget.of(context)!.num.toString()),
);
}
}
/* ---状态管理组件ShareDataWidget--- */
class ShareDataWidget extends InheritedWidget {
// 共享数据
final int num;
ShareDataWidget(this.num, {super.key, required super.child});
// of静态方法通过上下文,返回实例对象
static ShareDataWidget? of (BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<ShareDataWidget>();
}
// 共享数据变化时,是否通知相关依赖组件重新build
bool updateShouldNotify (ShareDataWidget oldWidget) {
return true;
}
}