In the last article we looked at the difference between a StatelessWidget and a StatefulWidget, which holds State and can Build itself. In this article, we will study the life cycle of State.
createState
In this article we have analyzed that the process of inserting the Element corresponding to the Widget into the Element Tree is implemented in the inflateWidget method:
Element inflateWidget(Widget newWidget, dynamic newSlot) {
final Key? key = newWidget.key;
final Element newChild = newWidget.createElement();
newChild.mount(this, newSlot);
return newChild;
}
Copy the code
CreateElement () is a StatefulElement object created:
<! -- StatefulWidget --> StatefulElement createElement() => StatefulElement(this);Copy the code
Let’s look at the logic of StatefulElement(this) :
<! -- StatefulElement --> StatefulElement(StatefulWidget widget) : state = widget.createState(), super(widget) { state._element = this; state._widget = widget; } final State<StatefulWidget> state;Copy the code
- Call the
widget.createState()
Method generates oneStateObject,StatefulElementObject holds thisstate; - stateHold againStatefulElementObjects, that is, they existA circular referenceRelationship.
- State also holds the StatefulWidget object.
The reference logic of the three is somewhat convoluted, which can be expressed in a graph as follows:
We see that the StatefulElement does not need to refer directly to the StatefulWidget because it holds State, and thus holds the StatefulWidget indirectly.
StatelessElement needs to hold the StatelessWidget directly.
mounted
<! -- State --> bool get mounted => _element ! = null;Copy the code
Mounted becomes true when _element is assigned.
initState
Attaching the inflateWidget method above, the newly created Element object calls the mount method.
Because StatefulElement does not override the mount method, the parent ComponentElement’s mount method is actually called.
<! -- ComponentElement --> void mount(Element? parent, dynamic newSlot) { super.mount(parent, newSlot); _firstBuild(); }Copy the code
StatefulElement’s _firstBuild method calls state.initState()
<! -- StatefulElement --> void _firstBuild() { try { // 1 final dynamic debugCheckForReturnedFuture = state.initState() as dynamic; } finally { } state.didChangeDependencies(); super._firstBuild(); }Copy the code
didChangeDependencies
From the above code, we can see that the didChangeDependencies method is called in _firstBuild, that is, the initState and didChangeDependencies methods are executed together in _firstBuild.
When we see performRebuild, state also calls the didChangeDependencies method when StatefulElement’s _didChangeDependencies becomes true.
<! -- StatefulElement --> void performRebuild() { if (_didChangeDependencies) { state.didChangeDependencies(); _didChangeDependencies = false; } super.performRebuild(); }Copy the code
When the value of the InheritedWidget changes, it is possible to change the value of _didChangeDependencies to true.
build
Let’s look at the super.performrebuild () method:
<! -- ComponentElement --> void performRebuild() { Widget? built; try { built = build(); }finally { } _child = updateChild(_child, built, slot); } <! -- StatefulElement --> Widget build() => state.build(this);Copy the code
The build method is called in the performRebuild method of StatefulElement, so state calls the build method.
didUpdateWidget
void update(StatefulWidget newWidget) { super.update(newWidget); final StatefulWidget oldWidget = state._widget! ; _dirty = true; state._widget = widget as StatefulWidget; try { final dynamic debugCheckForReturnedFuture = state.didUpdateWidget(oldWidget) as dynamic; } finally { } rebuild(); }Copy the code
When Element calls update, state calls the didUpdateWidget method. When the parent Widget causes a rebuild Build, the Update method is called if element can be reused.
setState
Mounted: true This method is called by the developer, and as long as mounted is true, Self rebuild can be implemented.
deactivate
The state deactivate method is called when an element changes from active to inactive.
void deactivate() {
state.deactivate();
super.deactivate();
}
Copy the code
At this point, element is removed from the Element Tree, but may be added back to the Tree if it can be reused.
dispose
State’s Dispose method is called when an Element changes from inactive to defunct.
void unmount() {
super.unmount();
state.dispose();
state._element = null;
}
Copy the code
mounted == false
State. _element = null; Mounted becomes false. State will be collected by the garbage collector.
conclusion
- inStatefulWidgetinstantiationStatefulElementObject
widget.createState()
createStateObject, and thenStateandStatefulElementMutual reference; - StateWith theStatefulElementAfter quoting,mountedbecomestrue, can be called
setState
Methods; - StatefulElementObject and then call
mount
Method to mount toElement TreeGo up. Called after mountinginitState
anddidChangeDependencies
Methods; - thenelementWill be called
performRebuild
Method is calledStatethebuild
Method, ifInheritedWidgetChanges in the value ofdidChangeDependencies
Methods; - The parent WidgetCause the refactoringBuildWhen, ifelementIt will be called if it can be reusedStatethe
didUpdateWidget
Methods; - whenelementfromactiveintoinactive“Will be calledstatethe
deactivate
Methods; - whenelementfrominactiveintodefunctIs calledstatethe
dispose
Method, and sets _element to null, and cannot be called againsetState
Methods; - Wait for the garbage collector to collect.