问题出在你的报价,这是不正确的.
正如您所说,InheritedWidget和其他小部件一样是不可变的.因此他们不会update岁.它们是重新创造的.
问题是:InheritedWidget is just a simple widget that does nothing but holding data.它没有任何更新或任何逻辑.
但是,与任何其他小部件一样,它与Element
相关联.
你猜怎么着?这个东西是可变的,Ffltter会在任何可能的情况下重复使用它!
更正后的报价如下:
以这种方式引用InheritedWidget时,当InheritedWidget与InheritedElement个更改关联时,将导致使用者重新构建.
There's a great talk about how widgets/elements/renderbox are pluged together美元.
但简而言之,它们是这样的(左侧是典型的小部件,中间是"元素",右侧是"渲染框"):
问题是:当你实例化一个新的小部件时;弗利特会把它和旧的相比.重用它的"元素",它指向一个渲染器.以及mutate个RenderBox属性.
Okey, but how does this answer my question ?
当实例化InheritedWidget,然后调用context.inheritedWidgetOfExactType
(或基本上相同的MyClass.of
)时;这意味着它将监听与您的InheritedWidget
相关联的Element
.并且每当Element
获得新的小部件时,它将强制刷新调用先前方法的任何小部件.
简而言之,当你用一个全新的替换现有的InheritedWidget
;弗利特会看到它变了.并将通知绑定的小部件可能的修改.
如果您了解所有内容,您应该已经猜到了解决方案:
把你的InheritedWidget
装进StatefulWidget
里面,只要有什么变化,它就会创造出一个全新的InheritedWidget
!
实际代码中的最终结果将是:
class MyInherited extends StatefulWidget {
static MyInheritedData of(BuildContext context) =>
context.inheritFromWidgetOfExactType(MyInheritedData) as MyInheritedData;
const MyInherited({Key key, this.child}) : super(key: key);
final Widget child;
@override
_MyInheritedState createState() => _MyInheritedState();
}
class _MyInheritedState extends State<MyInherited> {
String myField;
void onMyFieldChange(String newValue) {
setState(() {
myField = newValue;
});
}
@override
Widget build(BuildContext context) {
return MyInheritedData(
myField: myField,
onMyFieldChange: onMyFieldChange,
child: widget.child,
);
}
}
class MyInheritedData extends InheritedWidget {
final String myField;
final ValueChanged<String> onMyFieldChange;
MyInheritedData({
Key key,
this.myField,
this.onMyFieldChange,
Widget child,
}) : super(key: key, child: child);
static MyInheritedData of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<MyInheritedData>();
}
@override
bool updateShouldNotify(MyInheritedData oldWidget) {
return oldWidget.myField != myField ||
oldWidget.onMyFieldChange != onMyFieldChange;
}
}
But wouldn't creating a new InheritedWidget rebuild the whole tree ?个
不,不一定.因为新的InheritedWidget可能具有与以前完全相同的子级.确切地说,我指的是同样的情况.
具有与以前相同实例的小部件不会重新构建.
在大多数情况下(在应用程序的根目录下有一个inheritedWidget),inherited widget是constant.所以没有不必要的重建.