A stateful widget has the following lifecycle stages:
- createState()
- mounted == true
- initState()
- didChangeDependencies()
- build()
- didUpdateWidget()
- setState()
- deactivate()
- dispose()
- mounted == false
- createState()
- When Flutter is instructed to build a
StatefulWidget
, it immediately callscreateState()
. This method must exist. AStatefulWidget
rarely needs to be more complicated than this.
class MyHomePage extends StatefulWidget {
_MyHomePageState createState() => new _MyHomePageState();
}
- mounted is true
- When
createState
creates the state class, abuildContext
is assigned to that state. - A
BuildContext
is, overly simplified, the place in the widget tree in which this widget is placed. - All widgets have a bool
this.mounted
property. It is turns true when thebuildContext
is assigned. It is an error to callsetState
when a widget is unmounted.
- initState()
- This is the first method called when the widget is created (after the class constructor, of course.)
initState
is called once and only once. It must also callsuper.initState()
.- This @override method is the best time to: – Initialize data that relies on the specific
BuildContext
for the created instance of the widget. – Initialize properties that rely on this widgets ‘parent’ in the tree. – Subscribe toStreams
,ChangeNotifiers
, or any other object that could change the data on this widget.
initState() {
super.initState();
// Add listeners to this class
cartItemStream.listen((data) {
_updateWidget(data);
});
}
- didChangeDependencies()
- The
didChangeDependencies
method is called immediately afterinitState
on the first time the widget is built. - It will also be called whenever an object that this widget depends on data from is called. For example, if it relies on an
InheritedWidget
, which updates. build
is always called afterdidChangeDependencies
is called, so this is rarely needed. However, this method is the first change you have to callBuildContext.inheritFromWidgetOfExactType
. This essentially would make this State ‘listen’ to changes on a Widget it’s inheriting data from.- The docs also suggest that it could be useful if you need to do network calls (or any other expensive action) when an
InheritedWidget
updates.
- build()
- This method is called often (think fps + render). It is a required,
@override
and must return aWidget
. - Remember that in Flutter all gui is a widget with a child or children, even ‘
Padding
‘, ‘Center
‘.
- didUpdateWidget(Widget oldWidget)
didUpdateWidget()
is called if the parent widget changes and has to rebuild this widget (because it needs to give it different data), but it’s being rebuilt with the sameruntimeType
, then this method is called.- This is because Flutter is re-using the state, which is long lived. In this case, required is to initialize some data again, as one would in
initState()
. - If the state’s
build()
method relies on aStream
or other object that can change, unsubscribe from the old object and re-subscribe to the new instance indidUpdateWidget()
.
tip: This method is basically the replacement for ‘
initState()
‘ if it is expected theWidget
associated with the widgets’s state needs to to be rebuilt!
- Flutter always calls
build()
after this, so any subsequent further calls tosetState
is redundant.
void didUpdateWidget(Widget oldWidget) {
if (oldWidget.importantProperty != widget.importantProperty) {
_init();
}
}
- setState()
- The ‘
setState()
‘ method is called often from the Flutter framework itself and from the developer. - It is used to notify the framework that “data has changed”, and the widget at this build context should be rebuilt.
setState()
takes a callback which cannot be async. It is for this reason it can be called often as required, because repainting is cheap
void updateProfile(String name) {
setState(() => this.name = name);
}
- deactivate()
- This is rarely used.
- ‘
deactivate()
‘ is called whenState
is removed from the tree, but it might be reinserted before the current frame change is finished. This method exists basically becauseState
objects can be moved from one point in a tree to another.
- dispose()
- ‘
dispose()
‘ is called when theState
object is removed, which is permanent. - This method is where to unsubscribe and cancel all animations, streams, etc.
- mounted is false
- The state object can never remount, and an error is thrown is
setState()
is called.