Skip to content

How Flutter Handle State in StatefulWidget?

Flutter's state management within StatefulWidget is an essential part of how the framework creates responsive and interactive user interfaces. Here's a detailed overview of how Flutter keeps track of the states in StatefulWidget:

How Flutter Keeps Track of States

  1. Elements and Widgets:
  2. Flutter uses a combination of Widgets, Elements, and State objects to manage the lifecycle and rendering of UI components
  3. For a StatefulWidget, Flutter creates an associated State object that holds the mutable state for the widget

  4. Widget Lifecycle:

  5. When a StatefulWidget is inserted into the widget tree, Flutter creates a State object by calling the widget's createState method
  6. The State object persists across rebuilds, allowing it to maintain state throughout the widget's lifecycle

  7. Elements Tree:

  8. Flutter builds a tree of Element objects that map to the widget tree
  9. Each Element represents an instance of a widget in the tree and manages its lifecycle, including the creation, updating, and disposal of associated State objects

  10. State Object

  11. The State object, created by the StatefulWidget, holds all the mutable state for the widget.
  12. The State object has a setState method that, when called, indicates state changes and triggers a rebuild of the widget

Example: How Flutter Tracks State in a StatefulWidget

Here's a simple example to illustrate how Flutter tracks state in a StatefulWidget:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: CounterPage(),
    );
  }
}

class CounterPage extends StatefulWidget {
  @override
  _CounterPageState createState() => _CounterPageState();
}

class _CounterPageState extends State<CounterPage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Counter App'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

Detailed Explanation

  1. Creation:
  2. createState is called when the CounterPage widget is inserted into the tree, creating an instance of _CounterPageState

    @override
    _CounterPageState createState() => _CounterPageState();
    
    • Flutter creates an Element for the CounterPage widget
    • The Element holds a reference to the widget and the associated State object
  3. State Initialization:

  4. The _CounterPageState class extends State<CounterPage> and contains the mutable state _counter

    class _CounterPageState extends State<CounterPage> {
      int _counter = 0;
    
      void _incrementCounter() {
        setState(() {
          _counter++;
        });
      }
    }
    
  5. Rendering:

  6. Flutter calls the build method on the _CounterPageState object during the rendering phase

    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text('Counter App'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                'You have pushed the button this many times:',
              ),
              Text(
                '$_counter',
                style: Theme.of(context).textTheme.headline4,
              ),
            ],
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: _incrementCounter,
          tooltip: 'Increment',
          child: Icon(Icons.add),
        ),
      );
    }
    
  7. State Update (setState):

  8. When the _incrementCounter method is called, the setState method is invoked

    void _incrementCounter() {
      setState(() {
        _counter++;
      });
    }
    
    • The setState method does the following:
    • Marks the widget as dirty, indicating that it needs to be rebuilt
    • Schedules a new build phase where the build method is called again with the updated state
  9. Rebuild:

  10. During the build phase, Flutter calls the build method of _CounterPageState again, creating a new widget tree that reflects the updated state (_counter)

Lifecycle Methods in State Class

  • initState: Called when the State object is first created
  • didChangeDependencies: Called when the widget’s dependencies change
  • build: Called whenever the widget needs to be rebuilt
  • didUpdateWidget: Called when the widget is replaced with a new widget of the same type
  • dispose: Called when the State object is removed from the tree and will never be rebuilt

Summary

  • State Management:
  • Flutter uses State objects associated with StatefulWidgets to manage mutable state
  • setState is used to notify the framework of state changes, triggering a rebuild

  • Widget Lifecycle:

  • The State object persists across rebuilds and is managed by the Element tree, maintaining continuity and efficiency

  • Reactivity:

  • By calling setState, you ensure that UI components react to changes in state, allowing you to build dynamic and interactive applications

Flutter’s architecture ensures that state management is efficient and intuitive, allowing developers to maintain responsive and fluid user interfaces by using StatefulWidgets and setState effectively.