1. StatelessWidget
Định nghĩa: Là widget không có trạng thái (state). Giao diện của nó là cố định và không thay đổi trong suốt vòng đời của widget.
Đặc điểm:
Không thể cập nhật hoặc thay đổi giao diện sau khi đã được dựng.
Được sử dụng cho các UI không thay đổi hoặc chỉ hiển thị dữ liệu cố định.
Phương thức build
chỉ được gọi một lần khi widget được dựng.
2. StatefulWidget
Định nghĩa: Là widget có trạng thái (state) thay đổi được. Nó có thể cập nhật giao diện khi dữ liệu hoặc trạng thái thay đổi.
Đặc điểm:
Bao gồm hai lớp chính:
Lớp StatefulWidget
: Định nghĩa widget.
Lớp State
: Quản lý trạng thái của widget.
Giao diện có thể thay đổi khi setState
được gọi.
Được sử dụng khi widget cần phản ứng với sự thay đổi của dữ liệu (như click button, nhập liệu…).
Ví dụ dưới đây là đoạn code mặc định của flutter khi tạo project
– MyApp là một StatelessWidget
– MyHomePage là một StatefulWidget
Lưu ý: MyApp chứa MyHomePage
Bảng so sánh
Sự không phụ thuộc
StatefulWidget
độc lập trong việc quản lý trạng thái của nó, bất kể lớp cha là StatelessWidget
hay StatefulWidget
.
Điểm chính: StatefulWidget
có thể hoạt động bên trong StatelessWidget
, và điều này hoàn toàn hợp lệ vì Flutter cho phép tổ chức widget theo dạng cây widget (widget tree). Mỗi widget trong cây có thể hoạt động độc lập với loại của widget cha.
Ví dụ cụ thể : chúng ta thêm hai dòng chữ in ở mỗi widget để biết được widget nào đang được build lại thì rõ ràng MyHomePage được build lại mỗi lần thay đổi trạng thái số đếm
Full source code tham khảo
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
if (kDebugMode) {
print("StatelessWidget is called !");
}
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
if (kDebugMode) {
print("StatefulWidget is called !");
}
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}