一、InheritedWidget是什么?
官方说InheritedWidget是flutter中非常重要的一个功能性widget,它提供了一种数据在widget树中从上到下传递、共享的方式,比如我们在应用的根widget中通过InheritedWidget共享了一个数据,那么我们便可以在任意子widget中来获取该共享的数据!这个特性在一些需要在widget树中共享数据的场景中非常方便!
二、使用
class ShareDataWidget extends InheritedWidget{
int data;
ShareDataWidget({
@required this.data,Widget child}) : super(child: child);
//定义一个方法,方便子树中的widget获取这个widget,进而获得共享数据。
static ShareDataWidget of(BuildContext context,{
bool rebuild = true}){
if(rebuild){
return context.dependOnInheritedWidgetOfExactType<ShareDataWidget>();
}
// return (context.getElementForInheritedWidgetOfExactType<ShareDataWidget>()).widget;
return context.findAncestorWidgetOfExactType<ShareDataWidget>();
}
}
/**
* framework通过使用以前占据树中的这个位置的小部件作为参数调用这个函数来区分这些情况。
*/
@override
bool updateShouldNotify(ShareDataWidget oldWidget) {
return oldWidget.data != data;
}
}
dependOnInheritedWidgetOfExactType:
* 获取最近的给定类型的Widget,该widget必须是InheritedWidget的子类,
* 并向该widget注册传入的context,当该widget改变时,
* 这个context会重新构建以便从该widget获得新的值。
* 这就是child向InheritedWidget注册的方法。
当调用这个方法的时候,相应的子widget会调用didChangeDependencies这个方法。
findAncestorWidgetOfExactType:
功能与dependOnInheritedWidgetOfExactType一样,但是只会寻找InheritedWidget的子类,所以可以以O(1)的复杂度查找上级Widget。
当调用这个方法的时候,相应的子widget不会调用didChangeDependencies这个方法。
为什么会这样呢?原因在于dependOnInheritedWidgetOfExactType这个方法里面注册了InheritedWidget和其子widget注册了依赖关系。而findAncestorWidgetOfExactType没有。想看具体的话可以点进这两个方法的源码看看就知道了。
class TestWidget extends StatefulWidget{
final Widget child;
TopPage({
this.child});
@override
State<StatefulWidget> createState() {
return _TestWidgetState();
}
}
class _TestWidgetState extends State<TestWidget>{
int count=0;
@override
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
ShareDataWidget(
data: count,
child: widget.child,
),
RaisedButton( child: Text("Increment"),onPressed: () => setState(() => ++count)),
],
);
}
}
class ChildAWidget extends StatelessWidget{
@override
Widget build(BuildContext context) {
print("ChildAWidget build");
int test = ShareDataWidget.of(context,rebuild: true).data;
print(test);
return Container(child:
Text(test.toString())
,);
}
}
class ChildBWidget extends StatelessWidget{
@override
Widget build(BuildContext context) {
print("ChildBWidget build");
int test = ShareDataWidget.of(context,rebuild: false).data;
print(test);
return Container(child:
Text("ChildBWidget")
,);
}
}
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(128.0),
child: Center(child:TestWidget(
child: Column(
children: <Widget>[
ChildAWidget(),
ChildBWidget(),
],
),
)
),
));
上面的运行结果为如下,ChildAWidget 被build的,而ChildBWidget 不会被build
I/flutter (18210): ChildAWidget build
I/flutter (18210): 1
可以看到rebuild如果设置为true的话,那么他就会被rebuild,反之不会。
因此可以根据需要做一些局部的刷新操作,非常不错。
综上所述:如果层级嵌套的widget想共享同一份数据的话,便可通过调用ShareDataWidget.of(context).data 来实现获取共享数据,不用一层一层的传递数据了。
以上只是我做的一些浅显的学习,欢迎指教!完结撒花!
Flutter 之 InheritWidget 源码浅析(https://juejin.cn/post/6943189587061800996)