目录
InheritedWidget
一、介绍
InheritedWidget提供了一种在 widget 树中 从上到下共享数据的方式。
Flutter SDK中正是通过 InheritedWidget 来共享应用主题(Theme)和 Locale (当前语言环境)信息的。
我们创建一个继承自InheritedWidget 的 ShareDataWidget
class ShareDataWidget extends InheritedWidget {
const ShareDataWidget({
Key? key,
required this.data,
required Widget child,
}) : super(key: key, child: child);
final int data; //需要在子树中共享的数据,保存点击次数
//定义一个便捷方法,方便子树中的widget获取共享数据
static ShareDataWidget? of(BuildContext context) {
// context 实际是 element,通过当前element节点从element树中可以找到ShareDataWidget对用的element节点
// element持有Widget,就会找到ShareDataWidget
// 同时还会进行注册依赖关系,所以当data数据变化时,调用ShareDataChildWidget的didChangeDependencies()
return context.dependOnInheritedWidgetOfExactType<ShareDataWidget>();
// 如果只想引用ShareDataWidget数据,不希望在ShareDataWidget的data发生变化时调用ShareDataChildWidget的didChangeDependencies()方法使用下面的方法
// 该方法与上边的方法相比,不会进行关系注册
// return context.getElementForInheritedWidgetOfExactType<ShareDataWidget>()!.widget as ShareDataWidget;
}
//该回调决定当data发生变化时,是否通知子树中依赖data的Widget重新build
@override
bool updateShouldNotify(ShareDataWidget old) {
return old.data != data;
}
}
我们再创建一个使用了共享数据的 ShareDataChildWidget
class ShareDataChildWidget extends StatefulWidget {
ShareDataChildWidget({Key? key}):super(key: key);
@override
State createState() => _ShareDataChildWidgetState();
}
class _ShareDataChildWidgetState extends State<ShareDataChildWidget> {
@override
Widget build(BuildContext context) {
// return Text("text");
//使用InheritedWidget中的共享数据
return Text(ShareDataWidget.of(context)!.data.toString());
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
//父或祖先widget中的InheritedWidget改变(updateShouldNotify返回true)时会被调用。
//如果build中没有依赖InheritedWidget,则此回调不会被调用。
print("Dependencies change ${widget.key}");
}
}
二、应该在didChangeDependencies()中做什么?
一般来说子 widget 很少会重写此方法,因为在依赖改变后 Flutter 框架也都会调用build()方法重新构建组件树。
但是,如果你需要在依赖改变后执行一些昂贵的操作,比如网络请求,这时最好的方式就是在此方法中执行, 这样可以避免每次build()都执行这些昂贵操作。
也可以在data改变后不调用setState,避免build的调用,需要的逻辑在 didChangeDependencies 中进行,根据具体情况具体分析。
行者常至,为者常成!