Flutter Introduction | Using the State Class and Understanding StatefulWidget!!
In this article, we will explain StatefulWidget and create an app where the display dynamically changes when a button is pressed!!
Table of contents
- About StatefulWidget
- Manipulating State in StatefulWidget
- Handling FloatingActionButton Tap
- Using Complex Values
- summary
About StatefulWidget
The StatelessWidget we used in the previous article is a widget that does not have a state.
State is a mechanism for maintaining the state of an application.
In other words, if there is no state, the widget remains in the same condition as when it was first displayed and does not change.
However, in real applications, it is natural for the display to change dynamically.
An app that updates its display dynamically cannot be created using StatelessWidget.
That’s why we use StatefulWidget, which we will explain in this article.
StatefulWidget and State
The StatefulWidget class has the ability to handle state.
This functionality is provided by the State class.
To summarize, a StatefulWidget is defined in the following structure:
Basic Structure of a StatefulWidget Class
class widgetClass extends StatefulWidget {
@override
State<widgetClass> createState() => stateClass();
}
Basic Structure of the State Class
class stateClass extends State<widgetClass> {
…Omitted…
@override
Widget build(BuildContext context) {
…Omitted…
}
}
The StatefulWidget class consists of two parts:
- State part (State class) – Manages the state and updates the UI when necessary.
- Widget part (StatefulWidget class) – Defines the structure of the widget.
Widget Class
The widget class is defined by extending the StatefulWidget
class.
This class must implement the createState
method.
The createState
method is responsible for creating the state, and typically, it simply returns an instance of the state class.
State Class
The state class is created by extending the State
class.
When defining it, the widget class should be specified inside < >
.
This links the state class to the corresponding StatefulWidget.
The state class includes a build
method.
The build
method is called when the state is created and returns the widget that represents the current state.
In the widget class, the createState
method returns an instance of the state class.
This instance is then used in the state class, where the build
method generates the widget.
As a result, the widget created in the state class‘s build
method is displayed on the screen as the UI of the widget class.
The build
method is called frequently in Flutter
Do not think of build
as being called only when the instance is created.
Instead, understand it as a method of the State class responsible for generating the UI.
The build
method is also called whenever the state is updated—for example, when setState
is used to modify a value. It then recreates the UI and updates the display accordingly.
Manipulating State in StatefulWidget
Now, let’s implement a sample to manipulate the state.
Rewrite main.dart
as follows.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
final title = 'Flutter sample';
final message = 'sample message';
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: new MyHomePage(title: this.title, message: this.message),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
final String message;
const MyHomePage({super.key, required this.title, required this.message});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Text(
widget.message,
style: TextStyle(fontSize: 32.0),
));
}
}
When you run the program, a simple message is displayed.

This displays the screen using state, but no logic has been implemented yet to manipulate the state.
For now, it’s just a sample to demonstrate what a StatefulWidget looks like.
Linking with the State Class
Here, the MyHomePage
widget class is created as a StatefulWidget.
Additionally, the _MyHomePageState
state class is defined and set as the state for MyHomePage
.
Looking at the createState
method, we can see the following implementation:
@override
State<MyHomePage> createState() => _MyHomePageState();
The _MyHomePageState
instance is created and returned in the createState
method.
This makes _MyHomePageState
the state associated with MyHomePage
.
In the _MyHomePageState
class, the build
method returns a Scaffold
instance.
Scaffold Structure:
appBar
→ Contains anAppBar
, which displays the application title.body
→ Contains aText
widget to display a message.
This results in a screen with an app bar and a text message.
Passing Values from StatelessWidget
to StatefulWidget
Here, we introduce a new process:
Passing values from the StatelessWidget (which serves as the foundation of the app) to a StatefulWidget.
In the StatelessWidget
class (MyApp
), the following value is prepared:
final title = 'Flutter sample';
final message = 'sample message;
The final
keyword is specified, meaning the value cannot be changed.
In a StatelessWidget, we use fixed values like this.
These values are then passed to the StatefulWidget and used within it.
return MaterialApp(
title: 'Flutter Demo',
home: new MyHomePage(
title: this.title,
message: this.message
),
);
When creating an instance of MyHomePage
for the home
property, two values—title
and message
—are provided.
These values are assigned using this.title
and this.message
in the constructor.
In other words, the properties are passed as arguments when instantiating MyHomePage
.
In the MyHomePage
class, the constructor is defined as follows:
const MyHomePage({super.key, required this.title, required this.message});
In this class, the title
and message
properties are also defined.
The values passed as arguments are directly assigned to this.title
and this.message
.
This means that the values prepared in MyApp
are successfully passed to MyHomePage
.
Passing Data from MyHomePage
to _MyHomePageState
Now, let’s see how title
and message
stored in MyHomePage
are used inside _MyHomePageState
.
When _MyHomePageState
‘s build
method is called, it creates a Scaffold
instance to define the app’s structure.
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Text(
widget.message,
style: TextStyle(fontSize: 32.0),
)
);
In the Text
widget, we specify widget.title
and widget.message
as arguments.
What is widget
?
- So,
widget.title
refers toMyHomePage
‘stitle
property. widget
is a property available in theState
class.- It stores the instance of the associated
StatefulWidget
(in this case,MyHomePage
).
With this setup, the values stored in MyHomePage
can now be used inside _MyHomePageState
.
By referencing widget.title
and widget.message
, _MyHomePageState
can access the properties of MyHomePage
and use them to display content dynamically.
Handling FloatingActionButton Tap
Now that we understand the basics of StatefulWidget
, let’s modify our sample to change the displayed text when the button is tapped.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
final title = 'Flutter sample';
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: new MyHomePage(title: this.title),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({super.key, required this.title});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _message = 'Hello';
void _setMessage() {
setState(() {
_message = 'Tapped!';
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Text(
_message,
style: TextStyle(fontSize: 32.0),
),
floatingActionButton: FloatingActionButton(
onPressed: _setMessage,
tooltip: 'set message.',
child: Icon(Icons.star),
),
);
}
}
When you run the app, it will look like the image below.

When the button is tapped, the message display changes!!

It is a very simple example, but it includes the minimum necessary elements to demonstrate state changes through user interaction.
State Update and setState
State changes should be handled within a method inside the State class.
In this case, we define a method called _setMessage
to update the state.
void _setMessage() {
setState(() {
_message = 'Tapped!';
});
}
The _setMessage
method calls setState
, which notifies the State class that an update has occurred.
Key Points About setState
✔️ Notifies the framework that the state has changed.
✔️ Triggers the build
method, updating the UI.
✔️ Accepts a function as its argument, where the state-changing logic is placed.
In this sample, the _message
property is updated inside the function passed to setState
.
How the Update Works
When _message
changes, setState
triggers a rebuild, updating the displayed text.
The _message
property is modified inside setState()
.
Since _message
is used in Text(_message)
, the UI depends on this value.
About FloatingActionButton
The floatingActionButton
property in the Scaffold
widget is used to display a floating action button (FAB). This is a round button typically placed at the bottom-right of the screen, commonly used for primary actions in an app.
The FloatingActionButton is provided as a class in Flutter, allowing the creation of a floating, circular button commonly used for primary actions in an app.
In the provided sample, floatingActionButton
is set as follows:
floatingActionButton: FloatingActionButton(
onPressed: _setMessage,
tooltip: 'set message.',
child: Icon(Icons.star),
),
When creating a FloatingActionButton instance, you can provide various arguments to customize its behavior and appearance.
onPressed
(Action on Tap)
- In this case,
_setMessage
is assigned. - Specifies what happens when the button is tapped.
- Usually, a method is assigned to handle the action.
tooltip
(Hint Text)
- Useful for providing additional information about the button’s function.
- Defines the text that appears when the user long-presses the button.
child
(Content Inside the Button)
- Typically contains an icon but can also include other widgets.
- Specifies what is displayed inside the button.
When creating a FloatingActionButton instance, these properties can be specified as anonymous class elements within the widget’s constructor.
Among the various properties, the most crucial one is onPressed
.
Why is onPressed
Important?
- Triggers an event when the button is tapped.
- Specifies a method responsible for state changes.
- Executes an action linked to the button press.
How onPressed
Works
If the widget has an onPressed
property, it executes the assigned method.
When the button is tapped, an onPressed
event occurs.
While onPressed
is a crucial event for buttons, Flutter provides many other event handlers that respond to different user interactions.
The Icon
class is used to display icons in a Flutter app.
How the Icon
Class Works
- Supports color, size, and other styling options.
- Represents an icon visually.
- Requires an icon value from the
Icons
class.
The FloatingActionButton
(FAB) in Flutter requires at least two essential properties:
onPressed
→ Specifies what happens when the button is tapped.child
→ Defines the icon inside the button.
Using Complex Values
So far, we’ve only displayed simple text values, but StatefulWidgets can also handle more complex data structures.
Let’s define a Data
class and pass its instance to a StatefulWidget
.
Since the base MyApp class is exactly the same, we will omit it and only post the MyHomePage class and beyond.
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({super.key, required this.title});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
//Data Classes
class Data {
int _price;
String _name;
Data(this._name, this._price) : super();
@override
String toString() {
return _name + ':' + _price.toString() + 'yen';
}
}
class _MyHomePageState extends State<MyHomePage> {
//Sample data
static final _data = [
Data('Apple', 200),
Data('Orange', 150),
Data('Peach', 300),
];
Data _item = _data[0];
void _setData() {
setState(() {
_item = (_data..shuffle()).first;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Text(
_item.toString(),
style: TextStyle(fontSize: 32.0),
),
floatingActionButton: FloatingActionButton(
onPressed: _setData,
tooltip: 'set message.',
child: Icon(Icons.star),
),
);
}
}
Here, the _MyHomePageState
class has a _data
property that stores a list of Data
objects. When the button is tapped, a Data
object is randomly selected and displayed on the screen.

About the Data class
The Data
class is defined to handle data composed of multiple values. When dealing with complex values, it is common to define and use a class that organizes the necessary information.
class Data {
int _price;
String _name;
Data(this._name, this._price) : super();
@override
String toString() {
return _name + ':' + _price.toString() + 'yen';
}
}
In the Data
class, two properties, _name
and _price
, are defined. The constructor allows setting these properties using the provided arguments.
Additionally, the toString
method is overridden to format and return the data as a text string.
Configuring the Data instance
On the state class side, a list of Data
instances is prepared, and a random selection from the list is displayed.
First, a list of data items and a property to store the selected data are defined.
static final _data = [
Data('Apple', 200),
Data('Orange', 150),
Data('Peach', 300),
];
Data _item = _data[0];
The _data
property, which stores Data
instances, is declared as static final
because its contents do not change after initialization.
Additionally, the first item of _data
is assigned to _item
, ensuring that the initial data is displayed when the app starts.
The only remaining step is to implement the _setData
method, which randomly selects an item from the list and updates the state.
void _setData() {
setState(() {
_item = (_data..shuffle()).first;
});
}
Here, the value is retrieved using (_data..shuffle()).first
inside setState
.
shuffle()
is a method that randomly rearranges the items in a list.first
retrieves the first item from the shuffled list.
This allows a random item to be selected from _data
each time the method is called.
summary
This time, we explored StatefulWidget
, which allows dynamic value changes using state!
How was it?
Watching the text on the screen update dynamically is quite interesting, isn’t it?
In the next article, we will continue with Flutter layout, referencing the official documentation.
Wishing you a great Flutter development experience! 🚀
2025-03-21
0件のコメント
コメントはまだありません。最初の一人になりましょう!