Flutter Lifecycle: State Object Lifecycle [Part 1]

Jessica Jimantoro
5 min readMar 22, 2023

--

Realizing a sequence of events that occur in our app is important for developers to build a robust application.

Hey guys! It’s been a long time since I’m not writing!

Long story short, on March 18, I was given an opportunity to become a speaker on Women Techmakers & GDG Bogor for the International Women’s Day event. I brought up “Flutter Lifecycle: Exploring Flutter App Anatomy” topic.

So, I want to share this topic again on Medium with some additional details. And it’s a friendly topic to read for those who just started using Flutter.

We often do code without knowing what’s the thing behind it. From my perspective, the Lifecycle becomes the things in coders daily life that they’re not aware of. For example, some people use setState without knowing why it can make our performance worst if we use it improperly, and I also found that some people forbid using setState.

If you already know about the lifecycle, widget, or widget tree, you can directly jump into Part 2.

Let’s start!

What is Lifecycle?

Plant Lifecycle, Source: https://ecotree.green/en/blog/the-life-cycle-of-a-tree

From the illustration above, you can see there’s a seed that then grows into a tree, grows old and dies at the end, and go back to the start stage again. Yes, lifecycle refers to the stages a living thing goes through from birth to death.

There are many lifecycles in Flutter such as App Lifecycle, State Object lifecycle, Element lifecycle, Route lifecycle, etc. But, I will go for the well-known one, the State Object lifecycle.

Why Lifecycle is Important?

  1. Improve app performance
    For one of the examples, have you guys ever heard these phrases? “Don’t rebuild the widget if it’s not important” or “Be careful to use setState”, can affect the app performance.
  2. Help prevent memory leak
    When you do dispose, don’t forget to dispose the Stream, Controller, etc. to prevent the memory leak.
  3. Manage state changes
    For mutable state, you can set your UI dynamically.
  4. Debug issues regarding app behavior and performance
    To notice the issues, will be easier to notice when you know the lifecycle.

What is Widget?

The definition comes from Greg Spencer from the Flutter Engineering team (Source: Link 02:00). He said that Widget is a discrete block of an app’s UI containing:

  1. A static configuration
    StatefulWidget & StatelessWidget are called configuration.
  2. Persistent state (optional)
    This is optional because it only exists on StatefulWidget
  3. A render() method
    Render method is located on the render object which has to render our app’s UI.

Actually, Widget is immutable. But there’re some cases where you need to make it mutable. For the example, when you have a form contains text fields and submit button; then you want to make the condition when the text fields are empty, the button will got disabled. This is where you need to make a mutable widget.

In Flutter, you can create a StatefulWidget, but how about the “Widget is immutable” statement? StatefulWidget has to do createState(), this is where you can have your mutable State. So, the state will be attached to the widget. And this state has a lifecycle, and this is what we will be talking about.

State Object Diagram

You can see that the State Object lifecycle starts from the State created until it gets disposed.

Sometimes, we create a StatefulWidget without realizing what’s going on because usually, the IDE does it for us.

class MyHomePage extends StatefulWidget {
const MyHomePage({ super.key });

@override
State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Center(
child: const Text('Hello World'),
);
}
}

Above, we have MyHomePage extends a StatefulWidget. The function that been overridden is createState() which returns the _MyHomePageState that extends the State. Inside the state, you can just override what method you want like initState, didChangeDependencies, etc.

Now, we’re going to analyze what’s happened on every single method in the Object State lifecycle.

Stateful Widget

abstract class StatefulWidget extends Widget {
const StatefulWidget({ super.key });

@override
StatefulElement createElement() => StatefulElement(this);

@protected
@factory
State createState();
}

From StatefulWidget, you can see it extends the Widget and it overrides the createElement method, which means every time you create a widget, you also create an element. And there is also a method that MyHomePage overrides, createState to connect the widget with your State class.

State

This is the State class that I already clean up the unneeded statement. You can see the detailed one on src/widgets/framework.dart on Flutter code.

abstract class State<T extends StatefulWidget> with Diagnosticable {
@protected
@mustCallSuper
void initState() { }

@mustCallSuper
@protected
void didUpdateWidget(covariant T oldWidget) { }

@protected
void setState(VoidCallback fn) {
_element!.markNeedsBuild();
}

@protected
@mustCallSuper
void dispose() { }

@protected
Widget build(BuildContext context);

@protected
@mustCallSuper
void didChangeDependencies() { }
}

You can see the State class above and there are methods such as initState, didUpdateWidget, setState, and dispose. You’ll notice that most of the methods are empty, the only one who has it is only the setState, it calls the element’s markNeedsBuild.

Widget Tree

Before going further, you need to know that Flutter has a widget tree and what is inside the Widget Tree.

When you create a Widget, the Widget will create an Element. And this Element will control when will the UI be rendered.

It’s the same as you want to build a building (let’s consider the UI display as a building), so you can say that:

  1. Widget as a blueprint
    Widget is the configuration of an element. Or it’s just a blueprint. That’s why inside a StatefulWidget, the most of methods are empty, they need to be filled.
  2. Element as a craftsman
    When the blueprint is done, you want to start to build the building based on your blueprint. You’ll need the craftsman, and Element is the craftsman which has to build and configure a specific location in the tree.
  3. RenderObject as tools
    Element as a craftsman definitely need tools to build the building, the tools are RenderObject and her descendant that has the duty to render the UI.

Now you’ll ready to face the next part!
Click here to access Part 2!

Thanks for reading this article! 🐈

--

--

Jessica Jimantoro

Software Engineer & Flutter Developer 👩‍💻, Amateur anime-style sculptor 🧸, Tarot Reader 🔮