# Flutter Mobile 101

> Dart, widget, MVVM + DI: đọc hiểu và build được một app Flutter thật chạy trên Android và iOS.

- URL: https://dantech.academy/courses/flutter-mobile-101
- Instructor: Dan Tech
- Chương trình học: 26 bài học
- English: https://dantech.academy/en/courses/flutter-mobile-101.md

Khóa nhập môn Flutter: nền tảng Dart và widget, tách app thành ba tầng MVVM, inject dependency bằng package provider, điều hướng bằng state machine và lưu dữ liệu local. Bạn học trên một repo app hoàn chỉnh - clone, chạy, đọc, rồi sửa từng phần đúng thứ vừa học.

## Yêu cầu

- Người mới
- Laptop (macOS nếu muốn chạy iOS)
- 1h/ngày

## Kỹ năng

- Dart essentials
- Flutter widgets & Material 3
- MVVM architecture
- Provider dependency injection
- Local persistence & testing

## Chương trình học

Gợi ý cho AI agent: mỗi bài học có bản Markdown ở URL của bài cộng `.md`. Bài miễn phí trả về toàn bộ nội dung, bài dành cho học viên trả về mục tiêu và dàn ý.

### Setup & App Đầu Tiên

toolchain sạch, app chạy trên máy thật với hot reload, và Git checkpoint làm lưới an toàn.

- [Cài Flutter SDK và flutter doctor](https://dantech.academy/courses/flutter-mobile-101/00-foundations-setup/lesson-01-install-flutter-sdk.md) (miễn phí): Cài Flutter SDK bản stable mới nhất từ repo chính thức của Flutter trên macOS, Windows, Linux, tự gõ lệnh hoặc giao cho AI coding agent, rồi đọc từng dòng flutter doctor và xử lý các cảnh báo thường gặp.
- [flutter create, flutter run và hot reload](https://dantech.academy/courses/flutter-mobile-101/00-foundations-setup/lesson-02-first-app-hot-reload.md) (miễn phí): flutter create, flutter run trên máy thật, cấu trúc thư mục ở mức cần thiết, và vòng lặp hot reload.
- [Git checkpoint, clone app đích và rules file cho AI](https://dantech.academy/courses/flutter-mobile-101/00-foundations-setup/lesson-03-git-checkpoints-ai-pair.md) (miễn phí): Commit theo checkpoint, nhận lời mời và clone app TicTac (quyền chỉ đọc) chạy trên máy thật, làm việc trên branch cá nhân, cập nhật code khi khóa học đổi, và khai stack của khóa trong rules file cho AI coding tool.

### Dart Essentials

đọc hiểu null safety, named params, sealed class, collections và async trong code AI sinh.

- [var, final, named parameters và null safety](https://dantech.academy/courses/flutter-mobile-101/01-dart-essentials/lesson-01-null-safety-and-functions.md): final và var, named parameters, null safety với ?. và ??, arrow function - đủ Dart để đọc mọi dòng code trong khóa.
- [Class, sealed class và pattern matching](https://dantech.academy/courses/flutter-mobile-101/01-dart-essentials/lesson-02-classes-sealed-and-patterns.md): enum có field và method, class bất biến với const constructor, sealed class, switch expression với pattern matching.
- [List, Map, Future và async/await](https://dantech.academy/courses/flutter-mobile-101/01-dart-essentials/lesson-03-collections-and-async.md): map, where, take trên List, cache bằng Map, collection-for và spread trong UI, Future với async/await.

### Widget Fundamentals

widget tree và layout, state và rebuild, danh sách và nhóm chip, constraints và kích thước, Stack chồng lớp, ba cây với const và key, BuildContext và InheritedWidget, vòng đời State với animation.

- [Widget tree, Column, Row và Expanded](https://dantech.academy/courses/flutter-mobile-101/02-widget-essentials/lesson-01-widget-tree-and-layout.md): Column, Row, GridView, Expanded, SizedBox, và cách đọc một widget tree lồng nhiều tầng.
- [StatelessWidget, StatefulWidget và setState](https://dantech.academy/courses/flutter-mobile-101/02-widget-essentials/lesson-02-state-and-rebuilds.md): StatelessWidget với StatefulWidget, setState kích hoạt rebuild, và lifting state up khi nhiều widget dùng chung một state.
- [collection-for, ListView.builder và Chip](https://dantech.academy/courses/flutter-mobile-101/02-widget-essentials/lesson-03-lists-and-selection.md): collection-for trong SingleChildScrollView, khi nào phải đổi sang ListView.builder, và nhóm chip chọn sinh từ enum.values.
- [BoxConstraints, Expanded và LayoutBuilder](https://dantech.academy/courses/flutter-mobile-101/02-widget-essentials/lesson-04-constraints-and-sizing.md): constraints go down, sizes go up, parent sets position; tight, loose và unbounded constraints; Expanded, AspectRatio, ConstrainedBox, FittedBox, LayoutBuilder, SafeArea.
- [Stack, Positioned và IgnorePointer](https://dantech.academy/courses/flutter-mobile-101/02-widget-essentials/lesson-05-stack-and-overlays.md): Stack với Positioned, IgnorePointer cho lớp trang trí, ClipRRect cắt góc, RepaintBoundary cô lập vẽ lại.
- [Widget, Element, RenderObject](https://dantech.academy/courses/flutter-mobile-101/02-widget-essentials/lesson-06-three-trees-const-and-keys.md): Ba nhánh của Element.updateChild, Widget.canUpdate, key quyết định State giữ hay mất, const đưa rebuild vào nhánh bỏ qua.
- [BuildContext và InheritedWidget](https://dantech.academy/courses/flutter-mobile-101/02-widget-essentials/lesson-07-buildcontext-and-inherited-widget.md): BuildContext là node trong element tree, .of(context) tra ngược lên cây, InheritedWidget đứng sau Theme, MediaQuery và provider.
- [State lifecycle và AnimationController](https://dantech.academy/courses/flutter-mobile-101/02-widget-essentials/lesson-08-state-lifecycle-and-animation.md): initState, didUpdateWidget, dispose, mounted; AnimationController với TickerProvider; implicit animation so với controller tự cầm.

### MVVM

ba tầng Model, ViewModel, View - domain không import Flutter, và bài test đầu tiên.

- [MVVM: Model, View, ViewModel in Flutter](https://dantech.academy/courses/flutter-mobile-101/03-mvvm/lesson-01-why-mvvm-and-three-layers.md): Ba giới hạn của setState khi app vượt một màn hình, trách nhiệm của Model, ViewModel, View, và tầng domain không import Flutter.
- [Immutable model và sealed class](https://dantech.academy/courses/flutter-mobile-101/03-mvvm/lesson-02-model-and-ui-state.md): MatchRecord với == viết tay, ScoreBoard và RoundState trả instance mới thay vì sửa tại chỗ, sealed class cho kết quả một ván và cho một lần đọc dữ liệu, và bài test đầu tiên.
- [ChangeNotifier và ListenableBuilder](https://dantech.academy/courses/flutter-mobile-101/03-mvvm/lesson-03-viewmodel-with-changenotifier.md): Ba ViewModel từ mỏng tới dày, ListenableBuilder nối View không cần thư viện ngoài, và dispose() đóng cả một lớp bug.

### Provider Và Dependency Injection

đưa ViewModel xuống cây widget, inject repository qua constructor và test ViewModel bằng fake.

- [Provider, MultiProvider và context.watch](https://dantech.academy/courses/flutter-mobile-101/04-provider-di/lesson-01-provider-package-basics.md): provider dựng trên InheritedWidget, MultiProvider ở composition root, và bốn cách đọc: watch, read, select, Consumer.
- [Dependency injection và composition root](https://dantech.academy/courses/flutter-mobile-101/04-provider-di/lesson-02-injecting-dependencies.md): buildProviders() đọc từng khối, vì sao không ViewModel nào ở app scope, vì sao repo không dùng ChangeNotifierProxyProvider, và hai seam Clock với Random.
- [Provider scope, Fake và fake_async](https://dantech.academy/courses/flutter-mobile-101/04-provider-di/lesson-03-scoping-and-testing.md): Scope quyết định vòng đời, ProviderNotFoundException khi nào là tin tốt, Fake viết tay thay mock framework, và test ViewModel có Timer bằng fake_async.

### Kiến Trúc Màn Hình

state machine năm màn thay cho navigator stack, nút back hệ thống, và khung quyết định state ở đâu.

- [Navigator stack và screen state machine](https://dantech.academy/courses/flutter-mobile-101/05-navigation/lesson-01-screen-state-machine.md): Navigator stack làm gì, vì sao app TicTac đổi màn bằng enum năm giá trị thay vì push và pop, và seam ScreenNavigator một method.
- [AppShell, ValueKey và PopScope](https://dantech.academy/courses/flutter-mobile-101/05-navigation/lesson-02-appshell-and-transitions.md): MaterialApp dựng trong AppShell, AppViewModel provide ở shell chứ không app-wide, switch exhaustive chọn màn, ValueKey remount, PopScope cho nút back Android.
- [ViewModel scope và shared repository](https://dantech.academy/courses/flutter-mobile-101/05-navigation/lesson-03-where-state-lives.md): Hai màn đọc chung repository thay vì gọi nhau, màn chơi tự mở ván khi hiện lên nên điều hướng là đủ, hiệu ứng ăn mừng sống ở shell, và bảng quyết định state nào đặt ở đâu.

### Ráp App Hoàn Chỉnh

tầng lưu trữ bốn lớp không crash khi dữ liệu hỏng, checklist ranh giới tầng, theme, debug và bản build cài được.

- [SharedPreferencesAsync và repository pattern](https://dantech.academy/courses/flutter-mobile-101/06-full-app/lesson-01-local-persistence-repository.md): Seam KeyValueStore, adapter SharedPreferencesAsync, JSON codec có số version, và repository làm nguồn sự thật với bốn nhánh đọc fail-soft.
- [main(), runApp và ráp toàn bộ app](https://dantech.academy/courses/flutter-mobile-101/06-full-app/lesson-02-assemble-the-app.md): main() load dữ liệu trước runApp, năm màn nối nhau ra sao, cây thư mục khi mọi thư mục đã có lý do, và checklist ranh giới tầng kiểm được bằng lệnh.
- [ColorScheme, debug và flutter build](https://dantech.academy/courses/flutter-mobile-101/06-full-app/lesson-03-theme-debug-and-ship.md): Hai ColorScheme viết tay thay vì sinh từ một màu, motion token tập trung, ba kỹ năng debug, chín thứ trông như bug mà không phải, và lệnh build cho Android lẫn iOS.
