颤振documentation for InheritedWidget说
基类小工具,有效地传播下来的树信息。
为了获得从>构建上下文插件继承特定类型的最近的实例,使用BuildContext.inheritFromWidgetOfExactType。
继承的窗口小部件,以这种方式引用时,会导致消费者重建时继承的部件本身的变化状态。
鉴于在颤振部件是不可变的,并且在该示例代码..
class FrogColor extends InheritedWidget {
const FrogColor({
Key key,
@required this.color,
@required Widget child,
}) : assert(color != null),
assert(child != null),
super(key: key, child: child);
final Color color;
static FrogColor of(BuildContext context) {
return context.inheritFromWidgetOfExactType(FrogColor);
}
@override
bool updateShouldNotify(FrogColor old) => color != old.color;
}
颜色属性是final
所以不能被重新分配。假设这个小部件正好处于树的顶部,因为在大多数例子中,当将这个不断是有用的。对于要更换小部件,一个新的实例将被创建。
据推测,这里做到这一点,无论是通过为孩子也将被创建,引起孩子的后代也重建,创造了其childresn等新情况的新实例..
结束了反正重建整个树。因此,通过使用inheritFromWidgetOfExactType
应用的选择性更新是没有意义的,当InheritedWidget实例的数据,该实例永远不会改变?
编辑:
这是什么,我不知道我可以放在一起简单的例子。在这个例子中,只有这样才能“变化”,这是靠近应用程序的根是有它的父(InheritedWidget/FrogColor
)的MyApp
重建。这将导致它重建其子女创造FrogColor
的新实例,并且被传递一个新的子实例。我没有看到任何其他方式的InheritedWidget/FrogColor
将改变其状态,如文档中
......将导致消费者重建时继承的部件本身的变化状态。
import 'package:flutter/material.dart';
import 'dart:math';
void main() {
runApp(MyApp());
}
class FrogColor extends InheritedWidget {
const FrogColor({
Key key,
@required this.color,
@required Widget child,
}) : assert(color != null),
assert(child != null),
super(key: key, child: child);
final Color color;
static FrogColor of(BuildContext context) {
return context.inheritFromWidgetOfExactType(FrogColor);
}
@override
bool updateShouldNotify(FrogColor old) => color != old.color;
}
class MyApp extends StatefulWidget {
// This widget is the root of your application.
MyAppState createState() => MyAppState();
}
class MyAppState extends State<MyApp>
{
@override
Widget build(BuildContext context) {
var random = Random(DateTime.now().millisecondsSinceEpoch);
return FrogColor(
color : Color.fromARGB(255,random.nextInt(255),random.nextInt(255),random.nextInt(255)),
child:MaterialApp(
title: 'Flutter Demo',
home: Column (
children: <Widget>[
WidgetA(),
Widget1(),
FlatButton(
child:Text("set state",style:TextStyle(color:Colors.white)),
onPressed:() => this.setState((){})
)
]
)
)
);
}
}
class WidgetA extends StatelessWidget {
@override
Widget build(BuildContext context) {
print("Ran Build ${this.runtimeType.toString()}");
return WidgetB();
}
}
class WidgetB extends StatelessWidget {
@override
Widget build(BuildContext context) {
print("Ran Build ${this.runtimeType.toString()}");
return Text("SomeText",style:TextStyle(color:FrogColor.of(context).color));
}
}
class Widget1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
print("Ran Build ${this.runtimeType.toString()}");
return Widget2();
}
}
class Widget2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
print("Ran Build ${this.runtimeType.toString()}");
return Text("SomeText",style:TextStyle(color:FrogColor.of(context).color));
}
}
此外,这样做的输出是
I/flutter (24881): Ran Build WidgetA
I/flutter (24881): Ran Build WidgetB
I/flutter (24881): Ran Build Widget1
I/flutter (24881): Ran Build Widget2
因此,所有的子控件总是重建。制作在inheritFromWidgetOfExactType毫无意义也做登记。
Aaditi:
为了应对在评论@RémiRousselet答案,修改上面的例子,像
class MyAppState extends State<MyApp>
{
Widget child;
MyAppState()
{
child = MaterialApp(
title: 'Flutter Demo',
home: Column (
children: <Widget>[
WidgetA(),
Widget1(),
FlatButton(
child:Text("set state",style:TextStyle(color:Colors.white)),
onPressed:() => this.setState((){})
)
]
)
);
}
@override
Widget build(BuildContext context) {
var random = Random(DateTime.now().millisecondsSinceEpoch);
return FrogColor(
color : Color.fromARGB(255,random.nextInt(255),random.nextInt(255),random.nextInt(255)),
child: child
);
}
}
通过存储应使同一子树传递给每个重建InhertedWidget不能构建功能之外修改树的作品。这不只是工作,导致已经与inheritFromWidgetOfExactType注册得到重建部件的重建,而不是其他。
虽然@RémiRousselet说,这是不正确的子树存储为国家,我不认为有任何理由,这是不正常的一部分,INFACT他们这样做在一些谷歌的视频教程。 Here她创造和保持为状态的一部分子树。在她的情况下,2 StatelessColorfulTile()部件。
据推测,这里做到这一点,无论是通过作为一个孩子也将被创建,引起孩子的后代也重建,造就了其子女等的新实例的新实例..
结束了反正重建整个树。
这就是你的困惑来自
一个widget重建不会强迫其后代重建。
当父重建,框架内部检查newChild == oldChild
,在这种情况下,孩子是不是重建。
因此,如果一个小部件的情况下并没有改变,或者如果它覆盖operator==
则有可能在其父被更新的窗口小部件不重建。
这也是为什么AnimatedBuilder
提供child
性质的原因之一:
AnimatedBuilder(
animation: animation,
builder: (context, child) {
return Container(child: child,);
},
child: Text('Hello world'),
);
这确保了当为动画的整个持续时间,child
被保留,因此不重建。导致更优化的UI。