Flutter life cycle | Deep Drive into Flutter Lifecycle

easy way to understand the flutter life cycle

Shirsh Shukla
9 min readOct 4, 2021

In this article, we will discuss the life cycle of flutter, everyone knows the life cycle in an internal part of our life, same as for coding,

in mobile development, every mobile application there is sort of things, they are doing one by one…
like if we open our application, so firstly they are creating designing of the app, step by step they are processing according to the situation.

like as you see any app Instagram or Twitter, if you open those, firstly they load data from the server then UI builds according to the data load from the server. then show data according to your usage and what application want to show you as it's needed, I think you understand what I want to describe.

so,
let's come to the main point, in every flutter application there are some life cycle methods. which calls according to the situation.

in a flutter, everything is a widget, mainly flutter application start from two states, StatelessWidget And StatefullWidget.

Stateless lifecycle

if your class extends from StatelessWidget, means this page just build of widget design inside there, but not update this,

if your class extends from StatefulWidget, means this is will be updated according to your requirement. It's a first-time build, then updates by your action.

Let’s start to discuss now firstly, the life cycle of StatefulWidget.

Stateful lifecycle
  • createState(): When the Framework is instructed to build a StatefulWidget, it immediately calls createState().

It creates the mutable state for this widget at a given location in the tree.
Subclasses should override this method to return a newly created instance of their associated State subclass:

_HomePageState createState() => _HomePageState();

The framework can call this method multiple times over the lifetime of a StatefulWidget. For example, if the widget is inserted into the tree in multiple locations, the framework will create a separate State object for each location. Similarly, if the widget is removed from the tree and later inserted into the tree again, the framework will call createState again to create a fresh State object, simplifying the lifecycle of State objects.

@override
void initState() {
super.initState();
}
  • initState(): This is the first method called when the widget is created (after the class constructor) initState is called once and only once. It must call super.initState().

It’s Called when this object is inserted into the tree.
The framework will call this method exactly once for each State object it creates.
Override this method to perform initialization that depends on the location at which this object was inserted into the tree (i.e., context) or on the widget used to configure this object (i.e., widget).

@override
void didChangeDependencies() {
super.didChangeDependencies();
}
  • didChangeDependencies(): This method is called immediately after initState on the first time the widget is built.

It’s Called when a dependency of this State object changes.
For example, if the previous call to build referenced an InheritedWidget that later changed, the framework would call this method to notify this object about the change.
This method is also called immediately after initState. It is safe to call BuildContext.dependOnInheritedWidgetOfExactType from this method.
Subclasses rarely override this method because the framework always calls build after dependency changes. Some subclasses do override this method because they need to do some expensive work (e.g., network fetches) when their dependencies change, and that work would be too expensive to do for every build.

@override
Widget build(BuildContext context) {
return Scaffold();
}
  • build(): This method is called often. It is required, and it must return a Widget.

It’s Describes the part of the user interface represented by this widget.
The framework calls this method in a number of different situations. For example:

After calling initState.

After calling didUpdateWidget.

After receiving a call to setState.

After a dependency of this State object changes (e.g., an InheritedWidget referenced by the previous build changes).

After calling deactivate and then reinserting the State object into the tree at another location.

This method can potentially be called in every frame and should not have any side effects beyond building a widget.
The framework replaces the subtree below this widget with the widget returned by this method, either by updating the existing subtree or by removing the subtree and inflating a new subtree, depending on whether the widget returned by this method can update the root of the existing subtree, as determined by calling Widget.canUpdate.
Typically implementations return a newly created constellation of widgets that are configured with information from this widget's constructor, the given BuildContext, and the internal state of this State object.
The given BuildContext contains information about the location in the tree at which this widget is being built. For example, the context provides the set of inherited widgets for this location in the tree. The BuildContext argument is always the same as the context property of this State object and will remain the same for the lifetime of this object. The BuildContext argument is provided redundantly here so that this method matches the signature for a WidgetBuilder.

@override
void didUpdateWidget(ProductSquare oldWidget) {
super.didUpdateWidget(oldWidget);
}
  • didUpdateWidget(): 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 same runtime type, then this method is called. This is because Flutter is re-using the state, which is long-lived. In this case, you may want to initialize some data again, as you would in initState.

It's Called whenever the widget configuration changes.
If the parent widget rebuilds and requests that this location in the tree update to display a new widget with the same runtimeType and Widget.key, the framework will update the widget property of this State object to refer to the new widget and then call this method with the previous widget as an argument.
Override this method to respond when the widget changes (e.g., to start implicit animations).
The framework always calls build after calling didUpdateWidget, which means any calls to setState in didUpdateWidget are redundant.
If a State’s build method depends on an object that can itself change state, for example, a ChangeNotifier or Stream, or some other object to which one can subscribe to receive notifications, then be sure to subscribe and unsubscribe properly in initState, didUpdateWidget, and dispose:

In initState, subscribe to the object.

In didUpdateWidget unsubscribe from the old object and subscribe to the new one if the updated widget configuration requires replacing the object.

In dispose, unsubscribe from the object.

Implementations of this method should start with a call to the inherited method, as in super.didUpdateWidget(oldWidget).

@override
void deactivate() {
super.deactivate();
}
  • deactivate(): Deactivate is called when State is removed from the tree, but it might be reinserted before the current frame change is finished. This method exists basically because State objects can be moved from one point in a tree to another.

Called when this object is removed from the tree.
The framework calls this method whenever it removes this State object from the tree. In some cases, the framework will reinsert the State object into another part of the tree (e.g., if the subtree containing this State object is grafted from one location in the tree to another due to the use of a GlobalKey). If that happens, the framework will call activate to give the State object a chance to reacquire any resources that it released in deactivate. It will then also call build to give the State object a chance to adapt to its new location in the tree. If the framework does reinsert this subtree, it will do so before the end of the animation frame in which the subtree was removed from the tree. For this reason, State objects can defer releasing most resources until the framework calls their dispose method.
Subclasses should override this method to clean up any links between this object and other elements in the tree (e.g. if you have provided an ancestor with a pointer to a descendant’s RenderObject).
Implementations of this method should end with a call to the inherited method, as in super.deactivate().

@override
void dispose() {
super.dispose();
}
  • dispose(): dispose() is called when the State object is removed, which is permanent. This method is where you should unsubscribe and cancel all animations, streams, etc.

It's called when this object is removed from the tree permanently.
The framework calls this method when this State object will never build again. After the framework calls dispose, the State object is considered unmounted and the mounted property is false. It is an error to call setState at this point. This stage of the lifecycle is terminal: there is no way to remount a State object that has been disposed.
Subclasses should override this method to release any resources retained by this object (e.g., stop any active animations).
If a State’s build method depends on an object that can itself change state, for example, a ChangeNotifier or Stream, or some other object to which one can subscribe to receive notifications, then be sure to subscribe and unsubscribe properly in initState, didUpdateWidget, and dispose:

In initState, subscribe to the object.

In didUpdateWidget unsubscribe from the old object and subscribe to the new one if the updated widget configuration requires replacing the object.

In dispose, unsubscribe from the object.

Implementations of this method should end with a call to the inherited method, as in super.dispose().

so, we discussed all the points regarding stateful lifecycle methods,

But, what about the application life cycle,
means if you open any page and not doing any action, or which function will be called when the screen will be visible to the user, for android or ios. let’s see for this,

AppLifecycleState ( The application is visible and responding to user input)

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.inactive) {
}else if (state == AppLifecycleState.paused) {
}else if (state == AppLifecycleState.resumed) {
}else if (state == AppLifecycleState.detached) {
}
}
application life
  • inactive - The application is in an inactive state and is not receiving user input. it's only for iOS. application is in an inactive state and is not receiving user input.

On iOS, this state corresponds to an app or the Flutter host view running
in the foreground inactive state. Apps transition to this state when in
a phone call, responding to a TouchID request when entering the app
switcher or the control center, or when the UIViewController hosting the
Flutter app is transitioning.

On Android, this corresponds to an app or the Flutter host view running
in the foreground inactive state. Apps transition to this state when
another activity is focused, such as a split-screen app, a phone call,
a picture-in-picture app, a system dialog, or another window. Apps in this state should assume that they may be paused at any time.

  • paused - The application is not currently visible to the user, not responding to user input, and running in the background.
    application is not currently visible to the user, not responding to user input, and running in the background. When the application is in this state, the engine will not call the PlatformDispatcher.onBeginFrame and PlatformDispatcher.onDrawFrame callbacks.
  • resumed - The application is visible and responding to user input.
  • suspending - The application will be suspended momentarily. is only for Android detached
  • detached - The application is still hosted on a flutter engine but is detached from any host views. When the application is in this state, the engine is running without a view. It can either be in the progress of attaching a view when engine was first initialized, or after the view being destroyed due to a Navigator pop.

If you got something wrong? Mention it in the comments. I would love to improve. your support means a lot to me! If you enjoy the content, I’d be grateful if you could consider subscribing to my YouTube channel as well.

I am Shirsh Shukla, a creative Developer, and a Technology lover. You can find me on LinkedIn or maybe follow me on Twitter or just walk over my portfolio for more details. And of course, you can follow me on GitHub as well.

Have a nice day!🙂

--

--

Shirsh Shukla

SDE at Reliance Jio | Mobile Application Developer | Speaker | Technical Writer | community member at Stack Overflow | Organizer @FlutterIndore