State Management

Learn the basic concept of state management and how to use it to build an interactive mobile app.

In this section, we are going to discuss the concept of states, the execution order of states, and how to manage states of the app. In Flutter, everything is widgets, and widgets are categorized into two types according to states. One stateless widget and another stateful widget. The stateless widget doesn't have any state, when a stateless widget gets built, then there is no any way to modify or change anything inside it. But in the stateful widget, we can modify its child structure and its appearance according to the need. Stateful widgets are very important to build interactive apps.

What is State:

The state is the set of information of the widget while building and modifying it while running App. Whenever you want to update or change the structure of widgets, you need to update the state of its widget which can be done by setState() method. setState() refresh the widgets build and update the user interface according to the recent changes on the state. 

State management is a very important procedure to build an interactive app. Flutter builds all the user interfaces according to the current declaration and state of your app.

How to Create Stateful Widget:

To create the stateful widget, you need to extend the widget build class with "StatefulWidget" like below.

import 'package:flutter/material.dart';

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

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

class HomePage extends StatefulWidget{
  @override
  State createState() {
    return _HomePage();
  }
}

class _HomePage extends State{
  @override
  Widget build(BuildContext context) {
    return Scaffold(
       appBar: AppBar( //appbar widget inside Scaffold
         title: Text("Stateful Widget")
       ),

       body: Center(
         child: Text("Stateful Widget"),
       )
    );
  }
}

In the code above, HomePage is stateful widget with child _HomePage() class which is extended to the state of its parent class. 

How to update State and Widgets in App

In an interactive and dynamic app, you may need to update the information and UI displayed in the app according to different conditions. In background, the states, values of variables may get changes but to update widgets setState() method is used. To show how to update the state and the widgets inside app, see the example below. In the example code below, we have a floating action button and one centered text with counter value. When user presses the floating action button, we will increase the counter value and update the displayed value on widget using setState().

import 'package:flutter/material.dart';

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

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

class HomePage extends StatefulWidget{
  @override
  State createState() {
    return _HomePage();
  }
}

class _HomePage extends State{
  int counter;

  @override
  void initState() { //inital state which is executed only on initial widget build.
    counter = 0;
    super.initState();
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
       appBar: AppBar( //appbar widget inside Scaffold
         title: Text("Stateful Widget")
       ),

       floatingActionButton: FloatingActionButton( 
          onPressed: (){
            setState(() { // setState to update the UI
               counter++; //during update to UI, increase counter value
            });
          },
          child: Icon(Icons.add), //add icon on Floating button
       ),

       body: Center(
         child: Text("Counter: $counter"), //display counter value
       )
    );
  }
}

Output: 

Initial Output Output after increment and setState()

Execution order in App:

If you are building an app, it is very important to understand the execution flow of code in your app. See the example code below and it's output to understand the flow of execution in Futter. 

import 'package:flutter/material.dart';

void main() {
   print("1. main method executed.");
   runApp(MyApp()); 
}

class MyApp extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    print("2. MyApp widget build.");
    return MaterialApp(
       home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget{
  @override
  State createState() {
    print("3. HomePage state build.");
    return _HomePage();
  }
}

class _HomePage extends State{
  int counter;

  @override
  void initState() { //inital state which is executed only on initial widget build.
    print("4. Initial state of _HomePage.");
    counter = 0;
    super.initState();
  }
  
  @override
  Widget build(BuildContext context) {
    print("5. Widget build of _HomePage.");
    return Scaffold(
       appBar: AppBar( //appbar widget inside Scaffold
         title: Text("Stateful Widget")
       ),

       floatingActionButton: FloatingActionButton( 
          onPressed: (){
            print("----button pressed----");
            setState(() { // setState to update the UI
               print("6. setState() after button press.");
               counter++; //during update to UI, increase counter value
            });
          },
          child: Icon(Icons.add), //add icon on Floating button
       ),

       body: Center(
         child: Text("Counter: $counter"), //display counter value
       )
    );
  }
}

Output:

From the output above, you need to note down the following two points.

1. initState() is executed only one time before widget build.

2. Widget build repeats after setState().