问题
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