State, Widget, StatefulWidget, StatelessWidget, Vòng đời ứng dụng.
Trong bài viết tạo ứng dụng Hello World, tôi đã cho bạn xem code của một ứng dụng Flutter. Trong đó có rất nhiều các từ khoá mà bạn cảm thấy lạ đó là : StatelessWidget, StatefulWidget, creatState().. Trong những từ này nổi bật lên là State và Widget , vì vậy trong bài viết này tôi sẽ giải thích về State, Widget, StatefulWidget, StatelessWidget, Vòng đời ứng dụng . Đây là phần quan trọng trong tư duy lập trình ứng dụng Flutter.
Widget và State
Widget là gì ?
Widget trong tiếng anh có nghĩa là phụ tùng
Trong ứng dụng Flutter nó cũng có nghĩa tương tự như vậy. Các màn hình trong ứng dụng Flutter được tạo bởi các Widget lắp ghép lại với nhau.
Widget là các “configuration object” dùng để tạo lên ứng dụng Flutter. Như vậy, Tạo ứng dụng Flutter là tạo các Widget và liên kết chúng lại với nhau.
Xem lại ứng dụng HelloWorld, được tạo bởi các Widget
Trong sourcecode: StatelessWidget, StatefulWidget, MaterialApp, Scaffold, Text, Button, Center, Column, Row, Container, SizedBox, ListView, GridView… đều là những Widget có sẵn trong Flutter SDK.
Người phát triển ứng dụng có thể tự tạo các Widget dựa trên các Widget có sẵn hoặc từ các thư viện được thêm vào trong pubspec.yaml
State là gì
State trong tiếng Anh nghĩa là trạng thái
Trong Flutter, State là thông tin về một thứ gì đó được lưu trong bộ nhớ.
Ví dụ: Một ứng dụng đơn giản bao gồm một nút bấm (button) và một dòng Text hiển thị trên màn hình. Mỗi lần bấm nút đó thì dòng text trên màn hình lại thay đổi. Như vậy ta nói State của Text thay đổi hay State của Ứng dụng đã thay đổi mỗi khi nhấn nút.
State có thể được hiểu rộng ra,
Trong ứng dụng HelloWorld, bạn có thể thấy biểu diễn theo hai cách đó là dùng StatelessWidget, StatefulWidget.
StatelessWidget
StatelessWidget là một Widget có sẵn trong Flutter SDK, chỉ nhận dữ liệu và hiển thị dữ liệu thụ động không liên quan đến state.
Stateless trong Tiếng Anh nghĩa là : không State hay không trạng thái. Vậy StatelessWidget có nghĩa là Widget không State hay Widget không trạng thái.
StatefulWidget
Trái với StatelessWidget thì StatefulWidget là Widget có trạng thái, cũng là Widget có sẵn trong Flutter SDK.
Stateful có nghĩa là có State hay có trạng thái. Vậy StatefulWidget có nghĩa là Widget có State hay Widget có trạng thái.
Như vậy, mỗi khi bạn tạo một màn hình ứng dụng các bạn sẽ chọn StatelessWidget hoặc StatefulWidget, như ví dụ trong ứng dụng HelloWorld
1 2 3 4 5 6 7 8 9 |
// Sử dụng StatelessWidget class MyApp extends StatelessWidget{ ..... } // Sử dụng StatefulWidget class MyApp extends StatefulWidget{ ..... } |
Để hiểu sâu hơn về State, Widget, StatefulWidget và StatelessWidget chúng ta cùng xem lại ứng dụng mặc định khi tạo một Flutter project mới:
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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } // Class sử dụng StatelessWidget vì chỉ đơn thuần hiển thị Widget : MyHomePage // Thông thường, khi bắt đầu một ứng dụng , class đầu tiên sẽ extends StatelessWidget // và bên trong hàm build dùng Widget : MaterialApp class MyApp extends StatelessWidget { // Các widget lồng nhau để tạo lên một giao diện @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, ), home: MyHomePage(title: 'Flutter Demo Home Page'), ); } } // Class sử dụng StatefulWidget class MyHomePage extends StatefulWidget { // Hàm khởi tạo - Constructor MyHomePage({Key key, this.title}) : super(key: key); final String title; // Khởi Tạo State @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { int _counter = 0; // Hàm thay đổi State của biến _counter // Hàm setState() : giúp set lại State của màn hình ứng dụng và gọi lại hàm build lại State mới void _incrementCounter() { setState(() { _counter++; }); } @override Widget build(BuildContext context) { return Scaffold( // Tạo Appbar appBar: AppBar( title: Text(widget.title), ), // Hiển thị ở giữa body: Center( // Tạo cột child: Column( // Căn trục ở vị trí giữa mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ // Hàng một Text( 'You have pushed the button this many times:', ), // Hàng 2 Text( '$_counter', style: Theme.of(context).textTheme.headline4, ), ], ), ), // Mỗi khi nhấn nút sẽ gọi đến hàm _incrementCounter, và khi đó State của _counter lại được đặt lại và thay đổi lên màn hình floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', child: Icon(Icons.add), ), ); } } |
Kết quả:
Từ ví dụ trên, cho thấy rằng:
+ Màn hình ứng dụng được tạo bởi các Widget lồng vào nhau.
+ State của biến _counter và state của màn hình ứng dụng được thay đổi và cập nhật lại mỗi khi nhấn nút. Mỗi khi nhấn nút gọi lại hàm _incrementCounter, trong đó hàm setState() để set lại State của màn hình ứng dụng, giúp build lại màn hình.
+ Hàm setState() rất quan trọng trong việc thay đổi trạng thái của màn hình, giúp build lại màn hình.
+ StatelessWidget : được dùng để hiển thị đơn thuần và không liên quan đến State.
+ StatefulWidget : được class HomePage kế thừa để thể hiện sự thay đổi của state bên trong màn hình ứng dụng.
Vòng đời ứng dụng
Trong đoạn code ở trên, các bạn đã thấy khi kế thừa lớp StatelessWidget hay StatefulWidget thì đều thấy ghi đè( @override) các phương thức như : build, createState đúng không ?
Những điều đó là dấu hiệu của vòng đời ứng dụng Flutter.
Vòng đời ứng dụng Flutter thực ra chỉ là tên gọi cho một chu trình quản lý trạng thái (State) của một màn hình ứng dụng.
Một ứng dụng Flutter có nhiều màn hình khác nhau và mỗi màn hình đều có sự thiết lập chu trình quản lý trạng thái ( State).
Như vậy khái niệm vòng đời ứng dụng trong Flutter, chính là vòng đời của trạng thái (State) .
Vì là quản lý theo trạng thái ( State) nên chúng ta chia làm hai loại có state ( Stateful ) và không có State (Stateless).
+ Vòng đời ứng dụng chỉ dùng StatelessWidget
Vì chỉ sử dụng StatelessWidget, Màn hình ứng dụng chỉ đơn thuần là nhận và hiển thị dữ liệu, không liên quan đến State nên không có vòng đời.
Việc ghi đè (@ override ) phương thức build là dùng để render Graphic UI( user interface), hiển thị lên màn hình cho người dùng.
Xem ví dụ ứng dụng HellWorld bạn sẽ thấy việc chỉ sử dụng StatelessWidget để tạo lên một màn hình ứng dụng.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget{ // Hàm build dùng để render Graphic UI @override Widget build(BuildContext context) { // TODO: implement build return MaterialApp( home: Scaffold( // Tạo Appbar appBar: AppBar( title: Text("Hello World"), ), // Tạo nội dung App là Hello World và hiển thị ở giữa body: Center( child: Text("Hello World !"), ), ), ); } } |
+ Vòng đời sử dụng StatefulWidget
Xây dựng màn hình ứng dụng dùng StatefulWidget tức là liên quan đến việc quản lý State. Vì vậy nó cần chu trình quản lý trạng thái.
Trong một vòng đời có 7 trạng thái đó là : createState, initState, didChangeDependences, build, didUpdateWidget, deactive, dispose.
+ createState
Khi tạo class kế thừa đến StatefulWidget, hàm khởi tạo sẽ được yêu cầu gọi đầu tiên, bằng cách ghi đè phương thức createState.
1 2 |
@override _MyHomePageState createState() => _MyHomePageState(); |
hoặc:
1 2 3 4 5 |
@override State<StatefulWidget> createState() { // TODO: implement createState return _MyHomePageState(); } |
+ initState()
Hàm này được gọi ngay khi widget được tạo. Nếu bạn đã lập trình native Android thì nó tương tự như onCreate().
1 2 3 4 5 6 |
@override void initState() { // TODO: implement initState super.initState(); // Viết gì đó } |
+ didChangeDependencies()
Hàm được gọi ngay sau hàm initState() và được gọi lại khi dependency của State thay đổi.
1 2 3 4 5 |
@override void didChangeDependencies() { // TODO: implement didChangeDependencies super.didChangeDependencies(); } |
+ build()
Hàm này được gọi sau didChangeDependencies(). Tất cả graphic UI (User Interface) sẽ được render trong hàm này.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@override Widget build(BuildContext context) { // TODO: implement build return MaterialApp( home: Scaffold( // Tạo Appbar appBar: AppBar( title: Text("Hello World"), ), // Tạo nội dung App là Hello World và hiển thị ở giữa body: Center( child: Text("Hello World !"), ), ), ); } |
+ didUpdateWidget
Hàm này được gọi khi Widget configuration thay đổi. Sau khi hàm này được gọi thì hàm build sẽ được gọi, như vậy hàm setState được sử dụng trong hàm didUpdateWidget sẽ bị bỏ qua.
1 2 3 4 5 |
@override void didUpdateWidget(MyHomePage oldWidget) { // TODO: implement didUpdateWidget super.didUpdateWidget(oldWidget); } |
+ deactivate()
Hàm này được gọi khi State bị gỡ khỏi cây widget nhưng nó có thể xác nhận lại trước khi quá trình xoá kết thúc.
1 2 3 4 5 |
@override void deactivate() { // TODO: implement deactivate super.deactivate(); } |
+ dispose()
Hàm này được gọi khi State bị gỡ ngay lập tức khỏi cây widget và khi đó State không bao giờ được build trở lại.
1 2 3 4 5 |
@override void dispose() { // TODO: implement dispose super.dispose(); } |
Kết luận : Qua bài viết này, các bạn đã hiểu cơ bản về Widget, State, StatelessWidget, StatefulWidget và vòng đời ứng dụng hay chu trình quản lý trạng thái trong màn hình ứng dụng.
Những kết luận quan trọng các bạn nên nhớ:
+ Các màn hình ứng dụng Flutter được tạo bởi các Widget
+ Hàm setState trong class kế thừa StatefulWidget , giúp set lại State và build lại màn hình mỗi khi được gọi đến.
+ StatelessWidget – class kế thừa Widget này, chỉ nhận và hiển thị dữ liệu đơn thuần không liên quan đến state và không có vòng đời.
+ StatefulWidget – class kế thừa Widget này để tạo màn hình ứng dụng có vòng đời gồm 7 trạng thái là : createState, initState, didChangeDependencies, build, didUpdateWidget, deactivate, dispose.