Popular Searches
Popular Course Categories
Popular Courses

Updating UI dynamically using setState()

Updating UI dynamically using setState()

Flutter Fundamentals


 

Updating UI Dynamically Using setState() in Flutter

 


    Flutter applications are designed to respond to user interaction and changing data. When a value
    changes during the lifetime of a widget, the user interface may also need to change. In a
    StatefulWidget, Flutter provides setState() to notify the framework
    that the widget's mutable state has changed and that the relevant UI should be rebuilt.
 

 


    The basic pattern is:
    change state → call setState() → rebuild UI → display updated state.
    Flutter's official documentation describes setState() as the mechanism used by a State
    object to tell the framework that its state has changed and the widget should be redrawn.
 

 


    For professional Flutter learning and training, visit
    JustAcademy Flutter Training
    and use the
    Flutter Course Demo Registration
    page.
 

 


 

1. What Does Dynamically Updating the UI Mean?

 


    Dynamic UI means that the content, appearance, or behavior of the application changes while the
    application is running without manually rebuilding the entire application.
 

 

Examples of dynamic UI updates include:

 


       
  • Increasing or decreasing a counter.

  •    
  • Changing a button's text after it is clicked.

  •    
  • Showing or hiding a widget.

  •    
  • Changing the color of a container.

  •    
  • Changing a favorite icon.

  •    
  • Updating a shopping cart quantity.

  •    
  • Showing a loading indicator.

  •    
  • Updating a progress value.

  •    
  • Changing a selected tab.

  •    
  • Displaying data entered by the user.

  •  

 


    Flutter's stateful widgets are specifically designed for UI that can change in response to user
    interaction or changing data.
 

 


 

2. Understanding the State-Driven UI Concept

 


    Flutter uses a declarative approach to UI development. Instead of directly changing an existing
    widget on the screen, you update the data that represents the current state and let Flutter rebuild
    the appropriate UI from that state.
 

 

State
  |
  v
UI is described from the current State
  |
  v
State changes
  |
  v
setState()
  |
  v
Flutter schedules a rebuild
  |
  v
build()
  |
  v
Updated UI

 


    This means the UI should generally be treated as a representation of the current state.
 

 


 

3. What is setState()?

 


    setState() is a method of the Flutter State class. It is used to tell
    Flutter that mutable state associated with the State object has changed.
 

 

The basic syntax is:

 

setState(() {
  // Update state here
});

 

For example:

 

int count = 0;

setState(() {
  count++;
});

 


    Here, count is the state and setState() informs Flutter that the state has
    changed and the UI should be rebuilt.
 

 


 

4. Why Do We Need setState()?

 

Consider this code:

 

int count = 0;

void increment() {
  count++;
}

 


    The variable changes in memory, but Flutter has not been notified that the visible UI needs to
    reflect the new value.
 

 

The normal StatefulWidget approach is:

 

void increment() {
  setState(() {
    count++;
  });
}

 


    Now Flutter knows that the State has changed and schedules the State object for rebuilding.
 

 


 

5. Dynamic UI Update Flow

 

User Action
     |
     v
Button / Gesture / Input
     |
     v
Event Handler
     |
     v
State Variable Changes
     |
     v
setState()
     |
     v
Flutter Schedules Rebuild
     |
     v
build() Runs
     |
     v
New UI Based on State

 

Example

 

onPressed: () {
  setState(() {
    count++;
  });
}

 

The complete process is:

 


       
  1. User presses the button.

  2.    
  3. The onPressed callback executes.

  4.    
  5. The state variable changes.

  6.    
  7. setState() notifies Flutter.

  8.    
  9. The State object is scheduled for rebuilding.

  10.    
  11. The build() method runs again.

  12.    
  13. The updated state is used to describe the UI.

  14.  

 


 

6. StatefulWidget Structure

 


    Dynamic local UI updates using setState() are normally implemented inside a
    StatefulWidget.
 

 

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

  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  int value = 0;

  @override
  Widget build(BuildContext context) {
    return Text('$value');
  }
}

 


    The StatefulWidget represents the widget configuration, while the associated
    State object stores mutable values that can change.
 

 


 

7. Basic Counter Example

 


    A counter is one of the simplest ways to understand dynamic UI updates.
 

 

import 'package:flutter/material.dart';

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

  @override
  State<CounterPage> createState() => _CounterPageState();
}

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

  void increment() {
    setState(() {
      count++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Dynamic UI'),
      ),
      body: Center(
        child: Text(
          'Count: $count',
          style: const TextStyle(fontSize: 32),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: increment,
        child: const Icon(Icons.add),
      ),
    );
  }
}

 

How the Counter Updates

 


       
  1. Initially, count = 0.

  2.    
  3. The UI displays Count: 0.

  4.    
  5. The user presses the button.

  6.    
  7. increment() is called.

  8.    
  9. setState() increments the count.

  10.    
  11. Flutter schedules the State object for rebuild.

  12.    
  13. build() runs again.

  14.    
  15. The UI now displays the updated count.

  16.  

 


 

8. Updating UI with Increase and Decrease Buttons

 

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

  @override
  State<Counter> createState() => _CounterState();
}

class _CounterState extends State<Counter> {
  int count = 0;

  void increase() {
    setState(() {
      count++;
    });
  }

  void decrease() {
    setState(() {
      count--;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text(
          '$count',
          style: const TextStyle(fontSize: 40),
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: decrease,
              child: const Text('Decrease'),
            ),
            const SizedBox(width: 10),
            ElevatedButton(
              onPressed: increase,
              child: const Text('Increase'),
            ),
          ],
        ),
      ],
    );
  }
}

 


    Both buttons modify the same state variable. Each change is wrapped in setState() so
    that the displayed counter can update.
 

 


 

9. Updating Text Dynamically

 


    Text displayed by a Flutter application can change dynamically when the value used by the
    Text widget changes.
 

 

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

  @override
  State<MessageExample> createState() => _MessageExampleState();
}

class _MessageExampleState extends State<MessageExample> {
  String message = 'Welcome';

  void changeMessage() {
    setState(() {
      message = 'Hello Flutter!';
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text(
          message,
          style: const TextStyle(fontSize: 24),
        ),
        ElevatedButton(
          onPressed: changeMessage,
          child: const Text('Change Message'),
        ),
      ],
    );
  }
}

 


 

10. Updating Boolean State Dynamically

 


    Boolean state is useful when a UI element has two possible conditions, such as active/inactive,
    visible/hidden, selected/unselected, or enabled/disabled.
 

 

bool isActive = false;

void toggleStatus() {
  setState(() {
    isActive = !isActive;
  });
}

 

The UI can then use the value:

 

Text(
  isActive ? 'Active' : 'Inactive',
)

 


    The conditional expression changes the displayed text according to the current state.
 

 


 

11. Dynamically Showing and Hiding Widgets

 


    A common use of state is controlling whether a widget should appear on the screen.
 

 

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

  @override
  State<VisibilityExample> createState() => _VisibilityExampleState();
}

class _VisibilityExampleState extends State<VisibilityExample> {
  bool showMessage = true;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        if (showMessage)
          const Text(
            'This message is visible',
            style: TextStyle(fontSize: 22),
          ),
        ElevatedButton(
          onPressed: () {
            setState(() {
              showMessage = !showMessage;
            });
          },
          child: const Text('Toggle Message'),
        ),
      ],
    );
  }
}

 


    When showMessage changes, setState() causes the UI to rebuild and the
    conditional widget is either included or excluded from the widget tree.
 

 


 

12. Dynamically Changing Colors

 


    The appearance of a widget can also be controlled by state.
 

 

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

  @override
  State<ColorExample> createState() => _ColorExampleState();
}

class _ColorExampleState extends State<ColorExample> {
  bool isActive = false;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Container(
          width: 200,
          height: 200,
          color: isActive
              ? Colors.green
              : Colors.grey,
        ),
        const SizedBox(height: 20),
        ElevatedButton(
          onPressed: () {
            setState(() {
              isActive = !isActive;
            });
          },
          child: const Text('Change Color'),
        ),
      ],
    );
  }
}

 


    The container's color depends on isActive. Updating the state changes the UI on the
    next rebuild.
 

 


 

13. Dynamically Updating an Icon

 


    Icons can also be changed according to state. A common example is a favorite button.
 

 

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

  @override
  State<FavoriteExample> createState() => _FavoriteExampleState();
}

class _FavoriteExampleState extends State<FavoriteExample> {
  bool isFavorite = false;

  @override
  Widget build(BuildContext context) {
    return IconButton(
      onPressed: () {
        setState(() {
          isFavorite = !isFavorite;
        });
      },
      icon: Icon(
        isFavorite
            ? Icons.favorite
            : Icons.favorite_border,
      ),
    );
  }
}

 


    The icon changes between Icons.favorite and Icons.favorite_border
    according to the current state.
 

 


 

14. Dynamic UI with Checkbox

 

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

  @override
  State<TermsExample> createState() => _TermsExampleState();
}

class _TermsExampleState extends State<TermsExample> {
  bool accepted = false;

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Checkbox(
          value: accepted,
          onChanged: (value) {
            setState(() {
              accepted = value ?? false;
            });
          },
        ),
        Text(
          accepted
              ? 'Terms accepted'
              : 'Please accept the terms',
        ),
      ],
    );
  }
}

 


 

15. Dynamic UI with Switch

 

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

  @override
  State<SettingsExample> createState() => _SettingsExampleState();
}

class _SettingsExampleState extends State<SettingsExample> {
  bool notificationsEnabled = true;

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        const Text('Notifications'),
        Switch(
          value: notificationsEnabled,
          onChanged: (value) {
            setState(() {
              notificationsEnabled = value;
            });
          },
        ),
      ],
    );
  }
}

 


 

16. Dynamic UI with Slider

 

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

  @override
  State<SliderExample> createState() => _SliderExampleState();
}

class _SliderExampleState extends State<SliderExample> {
  double volume = 50;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text(
          'Volume: ${volume.toInt()}',
          style: const TextStyle(fontSize: 22),
        ),
        Slider(
          value: volume,
          min: 0,
          max: 100,
          onChanged: (value) {
            setState(() {
              volume = value;
            });
          },
        ),
      ],
    );
  }
}

 


    As the slider moves, the value changes and setState() updates the displayed volume.
 

 


 

17. Dynamic UI with TextField

 


    User input can be used to update other parts of the UI.
 

 

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

  @override
  State<NameExample> createState() => _NameExampleState();
}

class _NameExampleState extends State<NameExample> {
  final TextEditingController controller =
      TextEditingController();

  String name = '';

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        TextField(
          controller: controller,
          decoration: const InputDecoration(
            labelText: 'Enter your name',
          ),
        ),
        const SizedBox(height: 10),
        ElevatedButton(
          onPressed: () {
            setState(() {
              name = controller.text;
            });
          },
          child: const Text('Update Name'),
        ),
        Text(
          'Hello $name',
          style: const TextStyle(fontSize: 24),
        ),
      ],
    );
  }
}

 


 

18. Updating a List Dynamically

 


    A list can be modified dynamically by adding or removing items inside setState().
 

 

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

  @override
  State<DynamicListExample> createState() => _DynamicListExampleState();
}

class _DynamicListExampleState
    extends State<DynamicListExample> {
  final List<String> items = [];

  void addItem() {
    setState(() {
      items.add('Item ${items.length + 1}');
    });
  }

  void removeItem(int index) {
    setState(() {
      items.removeAt(index);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        ElevatedButton(
          onPressed: addItem,
          child: const Text('Add Item'),
        ),
        Expanded(
          child: ListView.builder(
            itemCount: items.length,
            itemBuilder: (context, index) {
              return ListTile(
                title: Text(items[index]),
                trailing: IconButton(
                  icon: const Icon(Icons.delete),
                  onPressed: () {
                    removeItem(index);
                  },
                ),
              );
            },
          ),
        ),
      ],
    );
  }
}

 


 

19. Updating Multiple State Variables

 


    Multiple related state variables can be updated inside the same setState() call.
 

 

bool isLoading = false;
String message = '';

void startLoading() {
  setState(() {
    isLoading = true;
    message = 'Loading...';
  });
}

 


    After the state changes, the build method can use both values to generate the new UI.
 

 


 

20. Dynamic Loading UI

 


    Loading indicators are a common real-world example of dynamic UI.
 

 

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

  @override
  State<LoadingExample> createState() => _LoadingExampleState();
}

class _LoadingExampleState extends State<LoadingExample> {
  bool isLoading = false;

  Future<void> loadData() async {
    setState(() {
      isLoading = true;
    });

    await Future.delayed(
      const Duration(seconds: 2),
    );

    if (!mounted) {
      return;
    }

    setState(() {
      isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: isLoading
          ? const CircularProgressIndicator()
          : ElevatedButton(
              onPressed: loadData,
              child: const Text('Load Data'),
            ),
    );
  }
}

 


    The UI changes from a button to a progress indicator while loading and returns to the button after
    the asynchronous operation completes.
 

 


 

21. Dynamic UI with Login State

 

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

  @override
  State<LoginExample> createState() => _LoginExampleState();
}

class _LoginExampleState extends State<LoginExample> {
  bool isLoggedIn = false;

  void login() {
    setState(() {
      isLoggedIn = true;
    });
  }

  void logout() {
    setState(() {
      isLoggedIn = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text(
          isLoggedIn
              ? 'Welcome User'
              : 'Please Login',
          style: const TextStyle(fontSize: 24),
        ),
        const SizedBox(height: 20),
        ElevatedButton(
          onPressed: isLoggedIn ? logout : login,
          child: Text(
            isLoggedIn ? 'Logout' : 'Login',
          ),
        ),
      ],
    );
  }
}

 


 

22. Dynamic UI with Tab Selection

 

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

  @override
  State<TabExample> createState() => _TabExampleState();
}

class _TabExampleState extends State<TabExample> {
  int selectedIndex = 0;

  final List<String> tabs = [
    'Home',
    'Profile',
    'Settings',
  ];

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: List.generate(
            tabs.length,
            (index) {
              return ElevatedButton(
                onPressed: () {
                  setState(() {
                    selectedIndex = index;
                  });
                },
                child: Text(tabs[index]),
              );
            },
          ),
        ),
        const SizedBox(height: 30),
        Text(
          'Selected: ${tabs[selectedIndex]}',
          style: const TextStyle(fontSize: 24),
        ),
      ],
    );
  }
}

 


    The selectedIndex variable stores the currently selected tab. When the user chooses
    another tab, setState() changes the index and the UI updates.
 

 


 

23. Dynamic Shopping Cart Quantity

 

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

  @override
  State<CartQuantity> createState() => _CartQuantityState();
}

class _CartQuantityState extends State<CartQuantity> {
  int quantity = 1;

  void increaseQuantity() {
    setState(() {
      quantity++;
    });
  }

  void decreaseQuantity() {
    if (quantity > 1) {
      setState(() {
        quantity--;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        IconButton(
          onPressed: decreaseQuantity,
          icon: const Icon(Icons.remove),
        ),
        Text(
          '$quantity',
          style: const TextStyle(fontSize: 24),
        ),
        IconButton(
          onPressed: increaseQuantity,
          icon: const Icon(Icons.add),
        ),
      ],
    );
  }
}

 


 

24. Dynamic UI with Parent and Child Widgets

 


    State does not always need to be managed by the widget displaying the final UI. A parent widget can
    own the state and pass the current value and callbacks to a child widget.
 

 

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

  @override
  State<ParentWidget> createState() => _ParentWidgetState();
}

class _ParentWidgetState extends State<ParentWidget> {
  bool active = false;

  void handleChanged(bool value) {
    setState(() {
      active = value;
    });
  }

  @override
  Widget build(BuildContext context) {
    return ChildWidget(
      active: active,
      onChanged: handleChanged,
    );
  }
}

class ChildWidget extends StatelessWidget {
  final bool active;
  final ValueChanged<bool> onChanged;

  const ChildWidget({
    super.key,
    required this.active,
    required this.onChanged,
  });

  @override
  Widget build(BuildContext context) {
    return Switch(
      value: active,
      onChanged: onChanged,
    );
  }
}

 


    In this pattern, the parent uses setState() because the parent owns the changing state.
    The child simply receives the state and reports user interaction through a callback.
 

 


 

25. Dynamic UI with Conditional Widgets

 


    State can determine which widgets appear in the widget tree.
 

 

bool isLoggedIn = false;

@override
Widget build(BuildContext context) {
  return Column(
    children: [
      if (isLoggedIn)
        const Text('Dashboard')
      else
        const Text('Login Required'),
    ],
  );
}

 


    When isLoggedIn changes inside setState(), the next build displays the
    appropriate widget.
 

 


 

26. Dynamic UI with Ternary Operator

 


    The ternary operator is often useful for displaying one of two UI configurations based on state.
 

 

Text(
  isOnline ? 'Online' : 'Offline',
)

 

Another example:

 

Icon(
  isFavorite
      ? Icons.favorite
      : Icons.favorite_border,
)

 


    The value of the state variable determines what Flutter describes during the build.
 

 


 

27. Dynamic UI and build()

 


    The build() method should describe what the UI should look like for the current state.
    When setState() is called, Flutter schedules the State object for rebuilding and
    build() can run again.
 

 

int count = 0;

void increment() {
  setState(() {
    count++;
  });
}

@override
Widget build(BuildContext context) {
  return Text(
    'Count: $count',
  );
}

 


    Notice that the build() method does not manually search for the existing Text widget and
    change its text. Instead, it describes the UI from the current value of count.
 

 


 

28. setState() Does Not Directly Modify the UI

 


    It is important to understand that setState() does not directly edit a widget that is
    already displayed.
 

 

Instead:

 

setState()
    ↓
State is marked for rebuild
    ↓
build()
    ↓
UI configuration is recreated
    ↓
Flutter updates the rendered result

 


    This distinction helps developers understand Flutter's declarative UI model.
 

 


 

29. Multiple setState() Calls

 


    Multiple setState() calls can be made when state changes at different points in the
    application. However, avoid unnecessary calls and keep related state changes together when
    appropriate.
 

 

Instead of unnecessarily separating related updates:

 

setState(() {
  name = 'Manish';
});

setState(() {
  age = 25;
});

 

You can often group them:

 

setState(() {
  name = 'Manish';
  age = 25;
});

 


    Grouping related synchronous changes can make the code easier to understand.
 

 


 

30. Updating UI After an Asynchronous Operation

 


    Dynamic UI is commonly used when an application waits for an asynchronous operation such as a
    network request.
 

 

bool isLoading = false;
String message = '';

Future<void> fetchInformation() async {
  setState(() {
    isLoading = true;
  });

  await Future.delayed(
    const Duration(seconds: 2),
  );

  if (!mounted) {
    return;
  }

  setState(() {
    isLoading = false;
    message = 'Data loaded successfully';
  });
}

 


    The first state update shows the loading UI. After the asynchronous operation finishes, the second
    state update displays the result.
 

 


 

31. Why mounted is Important

 


    An asynchronous operation can continue after a widget has been removed from the widget tree. Before
    updating State after an asynchronous operation, check whether the State object is still mounted
    when appropriate.
 

 

final result = await fetchData();

if (!mounted) {
  return;
}

setState(() {
  data = result;
});

 


    This helps avoid attempting to update a State object that is no longer active.
 

 


 

32. Dynamic UI with Form Validation

 


    State can be used to dynamically display validation or submission status.
 

 

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

  @override
  State<FormExample> createState() => _FormExampleState();
}

class _FormExampleState extends State<FormExample> {
  String message = '';

  void submitForm() {
    setState(() {
      message = 'Form submitted successfully!';
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        ElevatedButton(
          onPressed: submitForm,
          child: const Text('Submit'),
        ),
        const SizedBox(height: 10),
        Text(message),
      ],
    );
  }
}

 


 

33. Common Mistakes When Updating UI

 

Mistake 1: Forgetting setState()

 

count++;

 


    If the change is intended to update the widget's local UI, use setState().
 

 

setState(() {
  count++;
});

 

Mistake 2: Calling setState() in build()

 


    Avoid calling setState() directly from the build() method. The build
    method should primarily describe the UI from the current state.
 

 

Mistake 3: Performing Expensive Work Inside setState()

 


    Keep the callback passed to setState() focused on the actual state mutation.
 

 

Mistake 4: Updating State After dispose()

 


    Asynchronous callbacks should be handled carefully. Use mounted when appropriate
    before calling setState().
 

 

Mistake 5: Calling setState() Unnecessarily

 


    Only call setState() when the local State has changed in a way that requires the UI
    to update.
 

 


 

34. Best Practices for Dynamic UI Updates

 


       
  1. Keep mutable local state inside the appropriate State object.

  2.    
  3. Call setState() when local State changes and the UI needs to reflect the change.

  4.    
  5. Keep the setState() callback small and focused.

  6.    
  7. Keep expensive calculations outside the state mutation callback when practical.

  8.    
  9. Keep the build() method focused on describing the UI.

  10.    
  11. Avoid unnecessary setState() calls.

  12.    
  13. Use mounted appropriately after asynchronous operations.

  14.    
  15. Dispose controllers, timers, and other resources when required.

  16.    
  17. Keep state close to the widgets that need it when practical.

  18.    
  19. For state shared across many widgets, consider an appropriate broader state-management approach.

  20.  

 


 

35. Complete Dynamic UI Example

 


    The following example combines several concepts: a counter, dynamic message, toggle state, and
    dynamically changing UI.
 

 

import 'package:flutter/material.dart';

void main() {
  runApp(const MaterialApp(
    home: DynamicUIExample(),
  ));
}

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

  @override
  State<DynamicUIExample> createState() => _DynamicUIExampleState();
}

class _DynamicUIExampleState
    extends State<DynamicUIExample> {

  int count = 0;
  bool isActive = false;
  String message = 'Welcome to Flutter';

  void increaseCount() {
    setState(() {
      count++;
    });
  }

  void toggleStatus() {
    setState(() {
      isActive = !isActive;
    });
  }

  void changeMessage() {
    setState(() {
      message = 'UI Updated Successfully!';
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Dynamic UI Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(20),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              message,
              style: const TextStyle(fontSize: 24),
            ),

            const SizedBox(height: 20),

            Text(
              'Count: $count',
              style: const TextStyle(fontSize: 30),
            ),

            const SizedBox(height: 20),

            Text(
              isActive ? 'Active' : 'Inactive',
              style: const TextStyle(fontSize: 22),
            ),

            const SizedBox(height: 20),

            ElevatedButton(
              onPressed: increaseCount,
              child: const Text('Increase Count'),
            ),

            const SizedBox(height: 10),

            ElevatedButton(
              onPressed: toggleStatus,
              child: const Text('Toggle Status'),
            ),

            const SizedBox(height: 10),

            ElevatedButton(
              onPressed: changeMessage,
              child: const Text('Change Message'),
            ),
          ],
        ),
      ),
    );
  }
}

 

What This Example Demonstrates

 


       
  • Integer state with count.

  •    
  • Boolean state with isActive.

  •    
  • String state with message.

  •    
  • Multiple event handlers.

  •    
  • Multiple setState() calls.

  •    
  • Dynamic text updates.

  •    
  • Dynamic conditional values.

  •    
  • Flutter's rebuild-based UI model.

  •  

 


 

36. Real-World Examples of Dynamic UI

 


   
     
     
     
   
   
     
     
     
   
   
     
     
     
   
   
     
     
     
   
   
     
     
     
   
   
     
     
     
   
   
     
     
     
   
   
     
     
     
   
   
     
     
     
   
   
     
     
     
   
 
FeatureState ExampleDynamic UI Change
CounterInteger valueDisplayed number changes
FavoriteBooleanFavorite icon changes
LoginBooleanLogin/logout UI changes
Shopping CartQuantity/listCart quantity changes
LoadingBooleanButton/progress indicator changes
CheckboxBooleanSelection state changes
SliderDoubleValue display changes
FormInput/statusValidation or submission message changes
TabsIndexSelected tab/content changes

 


 

37. Interview Questions

 

Q1. What does dynamic UI mean in Flutter?


 


    Dynamic UI means that the application's displayed content or appearance changes according to
    changing state, user interaction, or other data.
 

 

Q2. How does setState() update the UI?


 


    It tells Flutter that the State object has changed and needs to be rebuilt. The State's
    build() method then describes the UI using the updated state.
 

 

Q3. Does setState() directly change a widget on the screen?


 


    No. It notifies Flutter that the State has changed. Flutter then schedules the relevant rebuild,
    and the updated UI is produced from the new state.
 

 

Q4. Why doesn't changing a variable automatically update the UI?


 


    Flutter needs to know when a State object has changed. For local StatefulWidget state,
    setState() provides that notification.
 

 

Q5. Can setState() update multiple variables?


 


    Yes. Multiple related state variables can be changed inside the same setState()
    callback.
 

 

Q6. Can setState() be used after an async operation?


 


    Yes, when the State object is still mounted. After an asynchronous operation, check
    mounted when appropriate before calling setState().
 

 

Q7. What is the role of build() in dynamic UI?


 


    The build() method describes the UI based on the current state. When state changes and
    a rebuild is scheduled, build() can run again to produce the updated UI.
 

 


 

38. Practice Exercise

 

Create a Flutter application called Student Dashboard with the following features:

 


       
  1. Create a StatefulWidget called StudentDashboard.

  2.    
  3. Display the student's name.

  4.    
  5. Add an Update Name button.

  6.    
  7. Create a counter for completed lessons.

  8.    
  9. Add Complete Lesson and Undo buttons.

  10.    
  11. Create an online/offline Switch.

  12.    
  13. Display the current status dynamically.

  14.    
  15. Add a checkbox for course completion.

  16.    
  17. Display a success message when the course is completed.

  18.    
  19. Use setState() for all local UI state changes.

  20.  

 

Expected Flow

 

User Interaction
       |
       v
State Variable Changes
       |
       v
setState()
       |
       v
build()
       |
       v
Updated Student Dashboard

 


 

39. Quick Revision

 


   
     
     
   
   
     
     
   
   
     
     
   
   
     
     
   
   
     
     
   
   
     
     
   
   
     
     
   
   
     
     
   
 
ConceptMeaning
Dynamic UIUI that changes according to state, user interaction, or changing data.
StateData that can change during the lifetime of a widget.
StatefulWidgetWidget structure used when mutable local state is required.
setState()Notifies Flutter that the State has changed and a rebuild is needed.
build()Describes the UI using the current state.
mountedIndicates whether the State is currently associated with a mounted element.
dispose()Cleans up resources when the State is permanently removed.

 


 

40. Key Takeaways

 


       
  • Dynamic UI changes when the underlying state changes.

  •    
  • setState() is commonly used for local StatefulWidget state.

  •    
  • Changing a state variable and notifying Flutter are separate concepts.

  •    
  • setState() tells Flutter that the State object needs to rebuild.

  •    
  • The build() method describes the UI based on the current state.

  •    
  • Counter, checkbox, switch, slider, favorite button, forms, and loading screens are common examples.

  •    
  • Multiple related state variables can be updated inside one setState() call.

  •    
  • Use mounted appropriately when asynchronous operations update State.

  •    
  • Avoid unnecessary setState() calls and expensive work inside the callback.

  •    
  • For larger shared application state, use an appropriate broader state-management approach.

  •  

 


 

41. Learning Resources

 

 


 

Conclusion

 


    Updating the UI dynamically using setState() is a fundamental Flutter development
    concept. The main idea is to keep changing information in State, update that information when a
    user action or other event occurs, and call setState() so Flutter knows that the UI
    should be rebuilt.
 

 

State Changes
     ↓
setState()
     ↓
Flutter Schedules Rebuild
     ↓
build()
     ↓
Updated UI

 


    Once this pattern is understood, developers can create interactive counters, forms, shopping carts,
    login screens, loading indicators, toggles, dynamic lists, dashboards, and many other Flutter
    interfaces.
 


whatsapp