Flutter trong phát triển di động: nó là gì, các khái niệm chính và cách hoạt động

Tác giả: IT Sectr Đã đăng: 2026-07-09 Thời gian đọc: 11 phút

Flutter là một framework UI của Google dành cho các ứng dụng đa nền tảng gốc. Theo Flutter Docs (2025), Flutter được sử dụng trong hơn 500.000 ứng dụng trên Google Play. Hiểu về Widget, StatefulWidget, BuildContext và cây kết xuất là nền tảng của phát triển Flutter.

Những điểm chính

  • Widget — khối xây dựng cơ bản. StatelessWidget (bất biến) vs StatefulWidget (có thể thay đổi với setState()).
  • Ba cây: Widget Tree (cấu hình), Element Tree (phần tử), RenderObject Tree (kết xuất).
  • BuildContext — truy cập InheritedWidget: Theme, MediaQuery, Navigator. InheritedWidget — truyền dữ liệu xuống dưới.
  • Navigator — ngăn xếp màn hình (Routes). Navigator 2.0 (Router) — điều hướng khai báo.
  • Hot Reload — tiêm thay đổi trong 1-2 giây. Giữ nguyên trạng thái. Hot Restart — khởi động lại hoàn toàn.

Flutter: kiến thức cơ bản về Widget, StatelessWidget và StatefulWidget

Widget — mô tả khai báo của một phần UI. Mọi thứ trong Flutter đều là Widget: từ một nút đến chính ứng dụng. Widget là cấu hình (không phải UI). StatelessWidget — Widget bất biến. build() được gọi một lần. Không có trạng thái. Được sử dụng cho nội dung tĩnh. StatefulWidget — Widget có thể thay đổi. Có đối tượng State có thể thay đổi. setState() — kích hoạt xây dựng lại. State — đối tượng có thể thay đổi gắn với StatefulWidget. Chứa dữ liệu có thể thay đổi.

StatelessWidget vs StatefulWidget

StatelessWidget — build() được gọi một lần. Phù hợp cho tiêu đề, biểu tượng, văn bản tĩnh. StatefulWidget — build() được gọi mỗi khi setState() được gọi. Phù hợp cho biểu mẫu, danh sách có thay đổi, bộ đếm thời gian. InheritedWidget — truyền dữ liệu xuống dưới mà không cần truyền rõ ràng qua hàm tạo. Theme, MediaQuery, Navigator — InheritedWidgets. BuildContext — vị trí của Widget trong cây. context.of<T>, context.watch<T>, context.select<T,R> — truy cập InheritedWidget.

dart
// Ví dụ Flutter Widget: StatefulWidget với setState
class CounterWidget extends StatefulWidget {
  const CounterWidget({Key? key}) : super(key: key);

  @override
  State<CounterWidget> createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  int _counter = 0;

  void _increment() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Flutter Counter')),
      body: const Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text('You have pushed the button:'),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _increment,
        child: const Icon(Icons.add),
      ),
    );
  }
}

Widget — cấu hình. StatelessWidget — bất biến. StatefulWidget — có thể thay đổi với setState(). IT Sectr khuyên bạn nên bắt đầu với StatelessWidget và chuyển sang StatefulWidget chỉ khi cần trạng thái.

Cây (Widget Tree, Element Tree, RenderObject Tree)

Flutter sử dụng ba cây để kết xuất hiệu quả. Widget Tree — cây cấu hình. Widgets được tạo thường xuyên (mỗi build), nhẹ. Element Tree — cây phần tử. Một phần tử cho mỗi Widget (nếu loại không thay đổi). Element — cầu nối giữa Widget và RenderObject. RenderObject Tree — cây kết xuất. Xử lý kích thước, vị trí, vẽ. RenderObject — nặng, hiếm khi được tạo. Flutter so sánh Widget Tree và cập nhật Element Tree, điều này kích hoạt cập nhật RenderObject Tree.

Keys và Element Tree

Key — định danh Widget trong Element Tree. ValueKey, ObjectKey, UniqueKey, PageStorageKey. Keys cho phép Flutter khớp các Widget cũ và mới trong quá trình xây dựng lại. Không có Keys, Flutter khớp theo loại Widget và vị trí. GlobalKey — truy cập State từ Widget khác. Được sử dụng cho: biểu mẫu phức tạp, hoạt ảnh, truy cập State trong kiểm thử. IT Sectr khuyên bạn nên sử dụng Keys cho danh sách (List.generate) và tránh GlobalKey trừ khi cần thiết.

Expanded — Widget lấp đầy không gian có sẵn trong Row/Column/Flex. Flexible — không bắt buộc lấp đầy (có thể nhỏ hơn). MediaQuery — InheritedWidget với thông tin thiết bị: kích thước màn hình, hướng, nền tảng, hệ số tỷ lệ văn bản. Theme/ThemeData — chủ đề tập trung. Theme.of(context) — truy cập. MaterialApp — Widget gốc để cấu hình định tuyến, chủ đề, ngôn ngữ. Scaffold — bố cục cơ bản với AppBar, Drawer, BottomNavigationBar. AppBar — bảng trên cùng.

Navigator — ngăn xếp tuyến đường (Routes). Navigator.push — mở màn hình (trả về Future). Navigator.pop — đóng (kèm kết quả). MaterialPageRoute — chuyển tiếp có hoạt ảnh (trượt từ phải). Named Routes — định danh chuỗi. onGenerateRoute — trình xử lý tập trung. Navigator 2.0 (Router + RouteInformationParser + RouterDelegate) — điều hướng khai báo cho web, deep linking và các kịch bản phức tạp.

Navigator 2.0 — điều hướng khai báo. Router — Widget trung tâm. RouteInformationParser — phân tích URL. RouterDelegate — quản lý ngăn xếp. GoRouter (gói) — trình bao bọc đơn giản hóa trên Navigator 2.0. Hỗ trợ: tuyến đường có tên, tham số, chuyển hướng, deep linking. IT Sectr khuyên bạn nên sử dụng GoRouter cho hầu hết các dự án và chỉ sử dụng Navigator 2.0 cho các kịch bản phức tạp (web, desktop).

Bất đồng bộ (FutureBuilder, StreamBuilder)

FutureBuilder — Widget xây dựng UI dựa trên Future. connectionState: none, waiting, active, done. Được sử dụng cho: yêu cầu HTTP, đọc cơ sở dữ liệu, bộ đếm thời gian. StreamBuilder — Widget cho Stream (luồng dữ liệu vô hạn). snapshot.data, snapshot.hasError, snapshot.hasData. Được sử dụng cho: WebSocket, Firebase, cập nhật vị trí. Cả hai Widget đều xây dựng lại khi nhận được dữ liệu mới.

Quản lý trạng thái

Provider — DI đơn giản + quản lý trạng thái. ChangeNotifierProvider, MultiProvider. Riverpod — thay thế hiện đại cho Provider: an toàn khi biên dịch, độc lập với BuildContext. Bloc — kiến trúc Event-Driven: Cubit (sự kiện đơn giản) vs Bloc (phức tạp). GetX — quản lý trạng thái nhẹ + DI + định tuyến. setState — đơn giản nhất, cho trạng thái cục bộ. IT Sectr khuyên bạn nên sử dụng Riverpod cho các dự án mới và Provider cho các dự án hiện có.

Chủ đề và thích ứng (MediaQuery, ThemeData)

MediaQuery — kích thước màn hình, hướng, nền tảng, textScaleFactor. MediaQuery.of(context).size.width. ThemeData — chủ đề ứng dụng: màu sắc, phông chữ, hình dạng. Theme.of(context).textTheme.bodyLarge. Hot Reload — tiêm mã vào ứng dụng đang chạy. Giữ nguyên trạng thái. Không hỗ trợ: thay đổi main(), biến toàn cục, trường tĩnh. Hot Restart — khởi động lại hoàn toàn ứng dụng (mất trạng thái). Hot Reload — lợi thế chính của Flutter cho nhà phát triển.

Loại Widget Mô tả Ví dụ
StatelessWidgetBất biến, build một lầnText, Icon, Padding, Center
StatefulWidgetCó thể thay đổi, setState xây dựng lạiTextField, Checkbox, AnimationController
InheritedWidgetTruyền dữ liệu xuống dướiTheme, MediaQuery, Navigator
ProxyWidgetTrình bao bọc cho Widget khácParentDataWidget (Positioned, Expanded)
RenderObjectWidgetTạo RenderObjectColumn, Row, Stack (tùy chỉnh)

StatelessWidget — cho nội dung tĩnh. StatefulWidget — cho nội dung động. InheritedWidget — cho DI. IT Sectr khuyên bạn nên sử dụng StatelessWidget theo mặc định và StatefulWidget chỉ khi cần thiết.

Bố cục đáp ứng

LayoutBuilder — thích ứng với kích thước cha. OrientationBuilder — thích ứng với hướng. Expanded vs Flexible — phân phối không gian trong Row/Column. MediaQuery — điểm ngắt cho máy tính bảng và máy tính để bàn. SafeArea — lề từ các phần tử hệ thống (notch, thanh trạng thái). AspectRatio — duy trì tỷ lệ. IT Sectr khuyên bạn nên sử dụng LayoutBuilder cho bố cục thích ứng và OrientationBuilder cho hướng ngang.

Kiểm thử (Widget, Integration, Unit)

Kiểm thử đơn vị — kiểm thử logic kinh doanh, kho lưu trữ, mô hình. dart test — chạy. Kiểm thử Widget — kiểm thử widget riêng lẻ. WidgetTester — pumpWidget, tap, enterText. Kiểm thử tích hợp — kịch bản hoàn chỉnh trên thiết bị/trình giả lập thực. Mockito — giả lập phụ thuộc. Golden tests — so sánh ảnh chụp màn hình (tệp golden). IT Sectr khuyên bạn nên kiểm thử Widget cho mỗi màn hình và kiểm thử đơn vị cho logic kinh doanh.

dart
void main() {
  testWidgets('Counter increments on tap', (tester) async {
    await tester.pumpWidget(const MaterialApp(home: CounterWidget()));

    expect(find.text('0'), findsOneWidget);

    await tester.tap(find.byType(FloatingActionButton));
    await tester.pump();

    expect(find.text('1'), findsOneWidget);
  });
}

Hoạt ảnh (Ngầm, Tường minh, Hero)

Hoạt ảnh ngầm — AnimatedContainer, AnimatedOpacity, AnimatedPadding, TweenAnimationBuilder. Thay đổi thuộc tính tự động tạo hoạt ảnh. Hoạt ảnh tường minh — AnimationController với Tween. forward() / reverse(). Hoạt ảnh Hero — Widget Hero với thẻ — hoạt ảnh chuyển tiếp giữa các màn hình. Hoạt ảnh so le — chuỗi hoạt ảnh với Interval. Lottie — tích hợp hoạt ảnh After Effects. Rive — hoạt ảnh tương tác (state machine). IT Sectr khuyên bạn nên sử dụng AnimatedContainer cho 80% trường hợp và AnimationController cho các kịch bản phức tạp.

dart
class AnimatedBox extends StatefulWidget {
  @override
  State<AnimatedBox> createState() => _AnimatedBoxState();
}

class _AnimatedBoxState extends State<AnimatedBox> {
  bool _expanded = false;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => setState(() => _expanded = !_expanded),
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeInOut,
        width: _expanded ? 200 : 100,
        height: _expanded ? 200 : 100,
        color: _expanded ? Colors.blue : Colors.red,
        child: const Center(child: Text('Tap me')),
      ),
    );
  }
}

Mạng (http, dio, graphql)

http — HTTP client đơn giản (get, post, put, delete). dio — client nâng cao với bộ chặn, thời gian chờ, thử lại, ghi nhật ký. graphql_flutter — GraphQL client cho Flutter. json_serializable — tạo fromJson/toJson qua chú thích. Retrofit Dart — HTTP client type-safe như Retrofit. WebSocket — qua web_socket_channel. Firebase — Cloud Firestore, Realtime Database, Cloud Functions. IT Sectr khuyên bạn nên sử dụng dio cho REST API và graphql_flutter cho GraphQL.

Flutter DevTools — bộ công cụ: Inspector (cây widget), Timeline (hiệu suất), Memory, Network, Logging. Profile mode — lập hồ sơ không gỡ lỗi. Performance overlay — FPS, thời gian xây dựng. Flame chart — biểu đồ ngọn lửa. DevTools — công cụ thiết yếu để tối ưu hóa ứng dụng Flutter trong sản xuất.

Flutter Web — biên dịch Flutter sang WASM (WebAssembly). CanvasKit (Skia) vs HTML renderer. CanvasKit — pixel-perfect, nhưng nặng hơn. HTML renderer — nhẹ, nhưng có hạn chế. WASM (Flutter 3.22+) — hiệu suất gốc. Thích ứng đáp ứng qua LayoutBuilder và MediaQuery. IT Sectr khuyên bạn nên sử dụng CanvasKit cho ứng dụng web desktop và HTML renderer cho trang web nội dung.

Câu hỏi thường gặp

Sự khác biệt giữa StatelessWidget và StatefulWidget là gì?

StatelessWidget — bất biến, build một lần. StatefulWidget — với State có thể thay đổi và setState().

Widget Tree, Element Tree và RenderObject Tree là gì?

Widget Tree — cấu hình. Element Tree — cầu nối. RenderObject Tree — kết xuất (kích thước, vẽ).

BuildContext và InheritedWidget là gì?

BuildContext — vị trí Widget trong cây. InheritedWidget — truyền dữ liệu xuống dưới (Theme, MediaQuery).

Navigator và Route hoạt động như thế nào trong Flutter?

Navigator — ngăn xếp màn hình. push() → pop(). Named Routes — tên chuỗi. Navigator 2.0 — khai báo.

Hot Reload hoạt động như thế nào trong Flutter?

Hot Reload — tiêm mã trong 1-2 giây, bảo toàn trạng thái. Hot Restart — khởi động lại hoàn toàn.

Tổng kết

  • Widget — mọi thứ đều là Widget. StatelessWidget vs StatefulWidget — sự phân đôi cơ bản.
  • Ba cây: Widget → Element → RenderObject. Widget — cấu hình, RenderObject — kết xuất.
  • BuildContext + InheritedWidget — truy cập Theme, MediaQuery, Navigator mà không cần truyền rõ ràng.
  • Navigator — ngăn xếp màn hình. Navigator 2.0 — điều hướng khai báo cho web và deep links.
  • FutureBuilder — cho Future. StreamBuilder — cho Stream (Firebase, WebSocket).
  • MaterialApp + Scaffold — khung ứng dụng. ThemeData — chủ đề tập trung.
  • Hot Reload — tính năng giết người của Flutter. Cập nhật mã trong vài giây với bảo toàn trạng thái.

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án