Photo by Maxim Zhgulev on Unsplash

Intro

In the previous article, we reviewed some basic concepts about Flutters widgets. So now it’s about time to dive into the Flutter widgets lyfecycle.

Lifecycle in Flutter

The process of creating and updating widgets is executed many times by the Flutter system. Depending on the widget type (stateful or stateless) different methods will be executed, but we will always receive notifications (via callbacks) that allow us to customize the widget behaviour.

In stateless widgets

Methods invoked when handling stateless widgets are pretty straightforward:

  1. To begin with, the (stateless) widget constructor is called.
  2. Once the constructor is executed, build() gets called automatically by the system. This method returns the new visual element that will be added to the widget tree (on the position specified by the BuildContext object received as param).
  class MyWidget extends StatelessWidget {

     //XXX: called 1st...
     MyWidget();

     //XXX: called 2nd...
     @override
     Widget build(BuildContext cntxt) {    
       return Row(...);
     }
  } 

As a result, the sequence diagram is quite simple:

Stateless widgets lifecycle

Piece of cake, right? Let’s check the next one…

In stateful widgets

Managing stateful widgets is also a no brainer:

  1. At first, the (stateful) widget constructor is invoked.
  2. After that, the createState() method gets called automatically by the system. This method must instantiate and return the state object that will be “binded” to this widget.
  class MyOtherWidget extends StatefulWidget {

     MyWidget();

     @override
     State createState() {    
       return _MyOtherWidgetState();
     }
  } 

  class _MyOtherWidgetState extends State<MyOtherWidget> {
     ... 
  }

Keep in mind that stateful widgets always have state (dynamic data updated over time), so a new class is required to encapsulate it.

The “state” class defined always extends from State<> and receives the widget type as a generic parameter. Moreover, the associated widget is directly accessible through the .widget property.

In this case, the diagram for this scenario is also self-explanatory:

Stateful widgets lifecycle

At this point, if you compare it with the previous one, you should be wondering… then who is responsible for creating the view for the widget? Because right now we are just creating a state object.

In state objects

State objects contain several methods in their life cycle. And one of them is an old friend, the build() method:

  class _MyOtherWidgetState extends State<MyOtherWidget> {
     
     @override
     Widget build(BuildContext cntxt) {    
       return Column(...);
     }

  }

So state objects are in fact responsible for building the user interface of the associated widget. Although this may seem weird at first, take into account that state objects:

  • hold the dynamic data that the widget will display
  • can force the system to redraw the UI

Considering this, it makes sense they decide how the data is displayed too. For instance, when a state object holds a data collection of users, it also establishes if the interface is a grid, a table, a list, etc.

In the main execution flow for a state object lifecycle, the following methods/callbacks are invoked:

  1. As usual, the (state object) constructor is called.
    Once the constructor has executed successfully, the associated widget is added to the tree and it is considered to be MOUNTED (meaning it has a BuildContext, a position in the tree).
  2. After that, initState() is called one time by the system automatically.
    This method is frequently used to perform initialization tasks, such as subscribing to data sources that emit items, formatting information that will be displayed, etc.
  3. Then didChangeDependencies() is also automatically called by the system. At this point, widget is considered to be DIRTY, because we have not displayed its content on the screen (meaning build() method has not executed yet).
    NOTE: if we’ve subscribed to data sources, this method will also be executed every time a new item is emitted.
  4. build() is called automatically by the system and the user interface is composed. Now the object is considered to be CLEAN.
  5. dispose() is called automatically by the system once the element is removed from the tree. This method is frequently used to clear resources: for example, unsubscribing from data sources.

Eventually some alternative flows can be executed too:

  1. setState() is executed every time we called it explicitly from our state class. Its execution marks the associated widget as DIRTY again and forces the system to repaint the UI later.
    This method is the key difference when comparing stateless vs. stateful widgets, because it gives us the ability to request updates “on demand” for our widget. It’s usually associated with user interactions (like clicking a button) in order to update the UI accordingly.
  2. didUpdateWidget() gets called automatically by the system every time a parent widget up in the hierachy updates its contents. Again, the widget binded to the state is marked as DIRTY and a repaint is scheduled.

If we put together all these execution flows and consider the internal states mentioned, we get the final diagram shown below:

State objects lifecycle

Wrapping up

  • Stateless widgets lifecycle just creates the corresponding object and specifies its visual UI.
  • Stateful widgets lifecycle invokes the constructor and determines the state object that will handle the dynamic data.
  • State objects lifecycle contains several callbacks. Updates and refreshments can be imposed by the system (when some element we are depending on changes) but also be forced by the state object itself.

If you want to play around, use Dartpad with these code samples in order to explore the Flutter widgets lifecycle:

Write you next time!

Join the Conversation

1 Comment

Leave a comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: