Introducing Flutter Apps: Their Mystifying Lifecycle
Have you ever wondered what the lifecycle of a Flutter app is like? Or do you know What are the “Lifecycle methods” that Flutter Developers encounter in their job interviews? We will look for the answer in this post.
Lifecycle methods play a significant role in building projects. When stateful widgets are created, lifecycle methods are started to be called in the specified order. Lifecycle methods proceed in a loop according to the change of the widgets we call or the change of the parent widget. Stateful widgets maintain a State. It knows we’ve changed something and redraws what needs to be redrawn on our screen.
initState()
initState() is considered an important lifecycle method in Flutter. initState() is a method called once when the Stateful Widget is inserted in the widget tree. We generally override this method if we need to do some sort of initialization work like registering a listener because, unlike build(), this method is called once. It must also call super.initState(). This method is called to initialize data that depends on the specific BuildContext and initialize data that need to execute before build().
didChangeDependencies()
didChangeDependencies() is called when a dependency of the State object changes or immediately after initState(). It might call didChangeDependencies() again if your state object depends on a changed inherited widget. 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. Subclasses rarely override this method because the framework always calls build after a dependency changes
build()
The framework calls build() after didChangeDependencies(). This function is used for rendering the widget every time it is called.
When you want to update your UI or if you click hot-reload, the Flutter structure modifies the build() strategy. 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.
For example, AnimatedWidget is a subclass of StatefulWidget that introduces an abstract Widget build(BuildContext context)
method for its subclasses to implement. If StatefulWidget already had a build method that took a State argument, AnimatedWidget would be forced to provide its State object to subclasses even though its State object is an internal implementation detail of AnimatedWidget.
didUpdateWidget()
The framework calls didUpdateWidget() when a parent widget makes a change or needs to redraw the UI. It is essentially called each time we hot reload the application for survey the updates made to the widget. When that happens, you’ll get the oldWidget instance as a parameter so you can compare it with your current widget and do any additional logic.
The framework always calls build after calling didUpdateWidget, which means any calls to setState in didUpdateWidget are redundant.
Implementations of this method should start with a call to the inherited method.
setState()
This method is often called 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. The framework then marks the widget as dirty and triggers a build() again. We can not call this method after dispose().
If you change the state directly without calling setState, the framework might not schedule a build and the user interface for this subtree might not be updated to reflect the new state.
Tip: Whenever you change the internal state of a State object, make that change in the setState() method.
deactivate()
When you remove the object from the tree, the framework calls deactivate().
The framework can, in some cases, reinsert the state object into another part of the tree. 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.
dispose()
The framework calls dispose() when you permanently remove the object and its state from the tree. This method is critical because you’ll need it to handle memory cleanups, such as unsubscribing streams and disposing of animations or controllers. The rule of thumb for dispose() is to check any properties you define in your state and make sure you’ve disposed of them properly. It is an error to call setState at this point. This lifecycle stage is terminal: there is no way to remount a State object that has been disposed.
Conclusion
In this article, I have tried to explain the Lifecycle of flutter. This is a small introduction to the app life cycle.
I hope I was able to answer your “What is the lifecycle in Flutter?” question with this blog I wrote.