问题
I have a Parent widget, which holds some state, a counter in this case.
This state is passed on to a Child widget using its constructor.
Now, how I understand it, the Child should get re-built every-time Parent's state changes, since it's inside the build() function of Parent, and build() gets called every-time the state changes.
This concept lead me to believe that the INIT STATE! message would be printed every time the counter changes. But it is not the case!
I essentially want a "hook" that gets fired only once, whenever the Child's constructor arguments (message) change.
Can someone please explain why this is the case, and what is the right way to have the aforementioned "hook"?
class Child extends StatefulWidget {
final String message;
const Child(this.message, {Key key}) : super(key: key);
@override
_ChildState createState() => _ChildState();
}
class _ChildState extends State<Child> {
@override
void initState() {
print("INIT STATE!");
super.initState();
}
@override
Widget build(BuildContext context) {
return Center(
child: Text(widget.message),
);
}
}
class Parent extends StatefulWidget {
@override
_ParentState createState() => _ParentState();
}
class _ParentState extends State<Parent> {
int _counter = 0;
@override
void initState() {
Timer.periodic(Duration(seconds: 1), (_) {
if (mounted) {
setState(() {
_counter += 1;
});
}
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Child(_counter.toString());
}
}
回答1:
Ok, looks like this was clearly mentioned in the State class' docs.
The correct way to do this is to override the didUpdateWidget method in the State subclass.
回答2:
Thanks to @Dev Aggarwal.
Extending to Dev Aggarwal's answer, i have included example here.
Implement didUpdateWidget() method in Child widget. When ever parent state changed, didUpdateWidget() method will call in child widget.
Implement didUpdateWidget() method in Child widget.
@override
void didUpdateWidget(<YourChildScreen> oldWidget) {
super.didUpdateWidget(oldWidget);
print("oldWidget.searchTerm is ${oldWidget.searchTerm}");
print("widget.searchTerm is ${widget.searchTerm}");
if (oldWidget.searchTerm != widget.searchTerm) {
this.updateChildWithParent();
}
}
void updateChildWithParent() {
print("updateChildWithParent/search screen");
setState(() {
_mJsonLoaded = false; // For loader
if (listArray.length > 0) {
listArray.clear();
}
});
// Do whatever you want here…
// Like call api call again in child widget.
}
I hope it will useful.
来源:https://stackoverflow.com/questions/54759920/flutter-why-is-child-widgets-initstate-is-not-called-on-every-rebuild-of-pa