在 Flutter 中,InheritedWidget
是一个非常重要的类,它允许沿着 widget 树向下传递数据。这种机制可以使得在 widget 树中较深层次的子 widget 能够访问由其祖先 widget 所持有的数据,而无需通过构造函数手动一层层传递。
基本概念
InheritedWidget
作为一个基类,通常不会直接使用。开发者会创建继承自 InheritedWidget
的自定义类,并在这个类中实现想要共享的数据和逻辑。
当一个 InheritedWidget
被插入到 widget 树中时,它会将自身注册到树上下文(context)中。这样,在树中任何位置的子 widget 都可以通过 context.dependOnInheritedWidgetOfExactType()
方法来获取最近的那个 InheritedWidget
实例,并访问其中包含的数据。
使用步骤
- 创建继承自
InheritedWidget
的类 :首先需要创建一个新的类并继承自InheritedWidget
。然后添加你希望共享给子 widgets 的数据作为成员变量。 - 实现
updateShouldNotify
方法 :这个方法用于决定当数据发生变化时是否应该通知依赖于此InheritedWidget
的子 widgets。如果返回 true,则依赖于此 InheritedWidget 的子 widgets 的didChangeDependencies()
方法将被调用。 - 提供静态方法以方便访问 :通常会在继承自
InheritedWidget
的类中提供一个静态方法来简化对共享数据的访问过程。 - 在 widget 树中使用:将你创建的 InheritedWidget 放置到 widget 树中合适的位置上,确保它能够覆盖到所有需要访问共享数据的子 widgets。
示例代码
dart
class MyData {
final String data;
MyData(this.data);
}
class MyInheritedWidget extends InheritedWidget {
final MyData myData;
MyInheritedWidget({
Key? key,
required this.myData,
required Widget child,
}) : super(key: key, child: child);
@override
bool updateShouldNotify(MyInheritedWidget old) {
return myData != old.myData;
}
static MyData of(BuildContext context) {
final MyInheritedWidget? result = context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
assert(result != null, 'No MyInherited found in context');
return result!.myData;
}
}
class SomeChild extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Accessing the data from the nearest MyInherited instance.
final myData = MyInheritedWidget.of(context).data;
return Text(myData);
}
}
在上面示例代码中:
- 我们定义了一个名为
MyData
的简单类来存储我们想要共享的数据。 - 创建了名为
MyInheritedWidget
的类,它继承自InheritedWidgеt
, 并且包含了我们想要共享出去的MyData
. - 在静态方法
of()
中,我们使用了上下文(context)来查找最近的那个类型为MyIhneritedWidgеt
的实例。 - 在某个子组件(如示例代码中的 SomeChild)里面,我们通过调用静态方法获取并显示了共享数据。
注意事项
- 当你调用
.of(context)
方法时,Flutter 将会把当前 widget 注册为依赖于找到的最近 InheriedWidgеt。因此当后者更新时前者也会重新构建。 - 如果你只是想读取 InheriedWidgеt 中包含的数据而不希望注册依赖关系(即不希望重新构建),可以使用
.getElementForIhneritedWidgеtOfExactType().widget as T
.
总之,Flutter 中的 InheriedWidgеt 提供了一种高效地在 widget 树间传递和共享数据状态而无需手动传递引用或回调函数等方式。