I. Introduction
When you build an app with Flutter, Widgets are indispensable, right? And two indispensable widgets are StatefullWidget and StatelessWidget. In this post I will share with you and these 2 widgets!
II. Detail
1. Widgets
- Widgets are the foundation of Flutter, a widget that represents part of the user interface. All components such as text, image, button or animation, theme, layout, or even app are a widget. In Flutter, all widgets or interfaces are coded using dart
- When a widget changes state, such as by user click or animation, the widget rebuilds itself to its new state. This saves developer time because UI can be described as a state functions. We don’t have to write extra code to only update the UI when the state changes.
- Widgets are simply classes. Example: class Text. Well so, if linking these elements, we can imagine a Widget class that has properties that store and display the Widget’s information like this:
1 2 3 4 5 6 | class Text { // Widget chỉ là class String text; // các property lưu trữ thông tin của widget Color textColor; // thông tin về màu sắc của text int fontSize; // thông tin về kích cỡ của font } |
2. Build function
Do you know the familiar math formula y = f (x). It is a function, when we have the value of x, based on a function f we get the value of y. Whenever x changes, it gives us a new value of y, right. Flutter is similar, it uses a formula of:
UI = f (Data)
When the Widget Data changes, the UI will be updated according to the formula f.
You see when I click on that blue button, the UI is changed to show different numbers, right. Number 0, 1, 2, 3, … that is the Data of the Widget. That data is stored in a variable of type int. When Data changes it will change the UI according to the formula f.
Thus, we have visualized the Widget Data and the build function and the relationship UI = build(Data)
. This is how Flutter works. We will go to the next definition of State
.
3. What is State
Suppose now, you create a Widget yourself as a light bulb. What information will the light bulb have:
- The size of the bulb is of type
int
. This information never changes. For example, the bulb when produced is size 20, 10 years later, it will also be size 20, but it cannot grow or shrink over the years, unless it is smashed (Widget die) =)) - The color is displaying the
Color
light, the default bulb color will be yellow, but sometimes it will change to red, sometimes it will be blue. This is changeable information, it will change once every few milliseconds. If the light color does not change, it could be damaged (Widget die) =))
So this class I named BulbLightWidget has 2 properties: size
(the size of the bulb) and currenLight (the color of the current bulb). The size
variable has a value that does not change forever, so it will declare the final height
, the variable currentLight
can be changed by reassigning the new value should declare var currentLight
or Color currentLight
.
1 2 3 4 5 | class BulbLightWidget { final size = 20; // height này cố định ko thay đổi nên để final Color currentLight = Colors.red; // màu đèn sẽ thay đổi từ đỏ, vàng, xanh } |
Thus, it is possible to divide the Widget’s data into two categories: Information that can be changed and information that cannot be changed.
And here is the simplest, most concise definition of State :
State is information shown on Widget that can change during the lifetime of the Widget
In that light bulb widget, that data currentLight
is state because it can be changed. When it changes, the BulbLightWidget
widget BulbLightWidget
to rebuild another interface. For example currentLight = Colors.red
, the widget displays a red light. When currentLight
changes to currentLight = Colors.green
, the widget must rebuild to display a green light. And the size is just normal data, not the state because it is always constant, the light bulb will forever be that big.
Okay, I understand that with Data, with a formula that is a build
function, I will build the UI. When Data changes, the build
function will be called back to update the UI (we call this the rebuild Widget). There are two types of widgets, StatefulWidget
and StatelessWidget
, each with a build
function, but the way they call the build
function to update the UI is different:
One is: StatefulWidget
, the Widget itself will actively update the UI. Second: StatelessWidget
, the Widget itself will passively update the UI, or in other words is forced to update the UI by another Widget. How is proactive, how is forced. We’ll come to the first way, to actively update the UI using the StatefulWidget
.
4. StatelessWidget
Stateless widgets have no state. It does not accept change within it. As for the change from outside (parent widget), it will passively change accordingly.
This means that StatelessWidget merely receives data and displays it passively. Interacting with it does not generate any event for itself to re-render. If you have to render again, it is due to external influences.
So, it has nothing to do with State at all. It itself does not have a createState
function, but instead is a build(BuildContext)
function build(BuildContext)
For example, we can see some samples of Stateless widgets .
Considering the type of Text widget is to initialize in a constructor and the properties are usually to build the widget and display it on the screen
5. StatefullWidget
StatefulWidget
is simply a Widget that has a CÓ State
ie it has changeable data. When the state changes, it calls the build
function again to rebuild the widget. Thanks to that, the UI changes.
Here is the structure of a StatefulWidget:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | class BulbLightWidget extends StatefulWidget { // 1 final size = 20; // mọi data trong class Widget phải immutable // data nào mutable xin mời qua class khác, là class State bên dưới :D // khi StatefulWidget được khởi tạo nó sẽ gọi hàm createState để tạo 1 object State @override State<StatefulWidget> createState() { return BulbLightState(); } } // khi object Widget gọi hàm createState thì object State ra đời class BulbLightState extends State<BulbLightWidget> { // 2 var currentLight = 'đỏ'; // hàm build @override Widget build(BuildContext context) { return Text('Kích thước đèn ${widget.size} và đèn đang có màu $currentLight'); // 3 } } |
Initially, when initializing StatefulWidget
, the build
function was called the first time, and it received a default state
to update UI: UI = build(default state)
. Every time we call setState function, it will call build function again to update new UI = build(new state)
: UI = build(new state)
Demo StatefullWidget
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: MyHomePage(), ); } } // Đây là một StatefulWidget class MyHomePage extends StatefulWidget { @override MyHomePageState createState() => MyHomePageState(); } // Đây là class State của StatefulWidget MyHomePage class MyHomePageState extends State<MyHomePage> { int counter = 0; // Data của Widget @override Widget build(BuildContext context) { // hàm build return Scaffold( body: Center( // data là biến counter được truyền vào hàm build - công thức UI = build(Data) child: Text('Tui là widget Text. Data của tui hiện tại là: $counter') ), floatingActionButton: FloatingActionButton( onPressed: () { // khi click button màu xanh blue setState(() { // ta sẽ gọi hàm setState counter++; // để gán lại giá trị mới cho biến counter // bên trong hàm setState này sẽ tự động gọi lại hàm build nên UI được update (rebuild) }); }, child: Icon(Icons.add), ), ); } } |
Here are the results:
III. Summarize knowledge
These are important knowledge in the article, I will summarize briefly as follows:
- Scene = f (Data) where
f
is thebuild
function contained in eachStatelessWidget
orStatefulWidget
. Flutter works according to that formula: When you change Data, the UI will be updated. State
is the Mutable data of the widget, soState
is the data of the Widget that can be changed.StatefulWidget
is widget withState
, whileStatelessWidget
is widget without State.StatefulWidget
can actively update UI by callingsetState
function.- Data in
StatelessWidget
cannot be changed, so if it wants to update the UI, you must ask the father of aStatefulWidget
to change the data to help it and then pass the data down to it through the constructor. - All data in the
StatefulWidget
andStatelessWidget
classes must be immutable - Use
StatelessWidget
as much as you can – your colleagues will love you.