Chương 01 · Flutter Setup

Flutter Setup — lên xe

Chương "lên xe" cho cả phần Flutter. Setup sai chỗ này thì 14 chương sau toàn debug môi trường thay vì học framework. Đặc biệt iOS Simulator / Xcode rất hay vướng — chương này dành nhiều section cho troubleshooting thực tế.

Độ dài: ~870 dòng Bài tập: 5 Quiz: 8 Prerequisites: Đã học xong 8 chương Dart
🎯 Mục tiêu chương
  • Cài Flutter SDK qua FVM (recommended) trên macOS.
  • Setup Android Studio + Xcode + iOS Simulator + Android Emulator.
  • Chạy flutter doctor và fix mọi warning.
  • Tạo project Flutter mới, hiểu cấu trúc folder sinh ra.
  • Chạy app trên 4 device: iOS Simulator, Android Emulator, Chrome (Web), macOS desktop.
  • Hiểu hot reload vs hot restart vs full rebuild.
  • Setup VS Code / Android Studio extension.
  • Phân biệt pubspec.yaml Flutter vs Dart console.

1. Flutter là gì?

Flutter là framework UI cross-platform do Google phát triển, ra mắt tháng 5/2017. Mục tiêu: "viết 1 lần, chạy mọi nơi" với native-quality UI.

Đặc điểm thiết kế:

  • Render engine riêng (Skia, gần đây là Impeller) — Flutter không dùng native widget của OS, mà tự vẽ pixel-perfect mỗi frame.
  • Multi-platform: iOS, Android, Web, macOS, Windows, Linux, embedded — cùng codebase.
  • Hot reload — sửa code thấy ngay không cần restart (development mode).
  • Declarative UI — UI là function của state, không phải manipulate DOM/UIKit.

Kiến trúc 3 layer

Flutter Architecture — 3 layer Framework (Dart) Widgets, Material, Cupertino, Rendering, Painting, Animation Engine (C++) Skia / Impeller, Dart runtime, text layout, accessibility Embedder (platform-specific) iOS Swift, Android Kotlin, Web JS, macOS/Windows/Linux
3 layer của Flutter: code Dart bạn viết ở layer Framework.
🔀 So với React Native, Native iOS/Android
FlutterReact NativeNative iOS/Android
UITự vẽ (Skia/Impeller)Bridge → native widgetNative widget thật
Ngôn ngữDartJS/TSSwift / Kotlin
PerformanceGần native (AOT)JS bridge overheadNative nhất
Hot reloadCó (rất nhanh)Có (Fast Refresh)Không (cần rebuild)
UI consistencyPixel-perfect cross-platformLook platform-nativePlatform-native

2. Cài Flutter qua FVM (recommended)

FVM (Flutter Version Manager) cho phép cài nhiều version Flutter, switch theo project. Recommended vì:

  • Mỗi project có thể require version Flutter khác nhau (vd app cũ stuck Flutter 3.10, app mới dùng 3.22).
  • Team sync version qua file .fvmrc commit vào git.
  • Update version không break project khác.
# macOS — qua Homebrew
brew tap leoafarias/fvm
brew install fvm

# Hoặc qua Dart pub
dart pub global activate fvm

# Verify
fvm --version

Cài version Flutter cụ thể:

# Liệt kê version available
fvm releases

# Cài stable mới nhất
fvm install stable

# Hoặc version cụ thể
fvm install 3.22.0

# Set làm global default
fvm global stable

# Verify
fvm flutter --version
# Output: Flutter 3.22.0 • channel stable ...

Setup PATH để gõ flutter trực tiếp (không cần fvm flutter):

# Thêm vào ~/.zshrc hoặc ~/.bashrc
export PATH="$PATH:$HOME/fvm/default/bin"
# Hoặc
export PATH="$PATH:$HOME/.fvm/versions/stable/bin"

# Reload
source ~/.zshrc

# Verify
flutter --version
which flutter

2.1 Cài Flutter raw (không qua FVM)

Nếu không muốn dùng FVM:

# Tải SDK từ flutter.dev/docs/get-started/install
# Giải nén vào ~/development/flutter

# Thêm vào ~/.zshrc
export PATH="$PATH:$HOME/development/flutter/bin"
source ~/.zshrc

flutter --version
💡 Tại sao FVM > raw?

Raw install: 1 version global cho toàn máy. Update Flutter có thể break project cũ.

FVM: switch version per project dễ dàng. cd project-a/ && fvm use 3.10, cd project-b/ && fvm use 3.22. File .fvmrc commit vào git — team mới clone tự dùng đúng version.

3. Setup iOS toolchain (macOS)

Để build iOS app, cần:

  1. Xcode — Mac App Store, ~10GB download. Cài bản mới nhất.
  2. Mở Xcode 1 lần — accept license + install additional components.
  3. Command Line Tools: xcode-select --install (nếu chưa có).
# Verify Xcode setup
sudo xcodebuild -runFirstLaunch
sudo xcodebuild -license accept

# Verify command line tools
xcode-select -p
# Output: /Applications/Xcode.app/Contents/Developer

CocoaPods — package manager cho iOS native code:

sudo gem install cocoapods
pod --version

iOS Simulator — built-in với Xcode:

# Mở Simulator
open -a Simulator

# Hoặc qua xcrun
xcrun simctl list devices
xcrun simctl boot "iPhone 15"

4. Setup Android toolchain

  1. Android Studio — tải từ developer.android.com. Cài full với SDK Manager + Emulator.
  2. Mở Android Studio → More ActionsSDK Manager → cài Android SDK Platform 34 (hoặc mới nhất) + Android SDK Build-Tools.
  3. Accept Android licenses:
flutter doctor --android-licenses
# Spam y để accept tất cả

Tạo AVD (Android Virtual Device):

  • Android Studio → More ActionsVirtual Device Manager.
  • Create Device → Pixel 7 → Tiramisu (API 33) hoặc Upside Down Cake (API 34).
  • Download system image nếu chưa có (~1GB).

5. flutter doctor — phải sạch

flutter doctor -v

# Output mẫu (đã pass)
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.22.0, on macOS 14.0 ...)
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 15.0)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2023.1)
[✓] VS Code (version 1.85.0)
[✓] Connected device (3 available)

Bảng troubleshoot 8 lỗi phổ biến

WarningNguyên nhânFix
[!] XcodeLicense chưa acceptsudo xcodebuild -license accept
[!] Android licensesChưa acceptflutter doctor --android-licenses
[!] CocoaPods missingGem chưa càisudo gem install cocoapods
[!] Android SDKSDK Manager chưa cài PlatformAndroid Studio → SDK Manager → cài API 33+
[!] ChromeKhông có Chrome browserCài Chrome (cho Web dev). Nếu không cần Web, ignore.
[!] Visual StudioBuild Windows desktopCài Visual Studio with C++ workload. Nếu không build Windows, ignore.
[!] HTTP Host AvailabilityMạng/firewall blockCheck pub.dev, fonts.gstatic.com — VPN nếu cần
[!] Connected deviceKhông có deviceMở Simulator / Emulator, hoặc cắm physical device
⚠️ Network issues ở VN

flutter doctor đôi khi báo "HTTP Host Availability failed" với storage.googleapis.com — Google service block. Fix: VPN hoặc FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn (mirror Trung Quốc, không khuyến nghị).

6. IDE setup

VS Code (recommended cho beginner)

  1. Cài Dart extension (Google official).
  2. Cài Flutter extension (đi kèm Dart, auto cài).
  3. Optional: Awesome Flutter Snippets — shortcut sinh widget nhanh.
  4. Optional: Error Lens — hiển thị error inline.

Settings recommend trong .vscode/settings.json hoặc User Settings:

{
  "[dart]": {
    "editor.formatOnSave": true,
    "editor.defaultFormatter": "Dart-Code.dart-code",
    "editor.rulers": [80, 100],
    "editor.tabSize": 2,
    "editor.selectionHighlight": false,
    "editor.suggest.snippetsPreventQuickSuggestions": false,
    "editor.suggestSelection": "first",
    "editor.tabCompletion": "onlySnippets",
    "editor.wordBasedSuggestions": "off"
  },
  "dart.lineLength": 100,
  "dart.previewFlutterUiGuides": true,
  "dart.previewFlutterUiGuidesCustomTracking": true,
  "dart.showTodos": false
}

Android Studio / IntelliJ IDEA

Cả 2 đều platform JetBrains. Plugin Flutter + Dart từ Marketplace. Ưu điểm: debugger Android mạnh hơn VS Code, refactoring tốt hơn. Nhược: nặng RAM.

💡 Recommend mix-and-match
  • VS Code cho dev hàng ngày (nhẹ, nhanh).
  • Android Studio khi cần debug Android native code hoặc edit android/ folder.
  • Xcode khi cần edit ios/ folder (signing, Info.plist, capability).

7. Tạo project Flutter đầu tiên

flutter create my_app
cd my_app
flutter run

Customize hơn:

flutter create \
  --org com.example.itbasic \
  --platforms=ios,android,macos,web \
  --description "My Flutter demo" \
  my_app

Cấu trúc folder sinh ra:

my_app/
├── lib/
│   └── main.dart          # Entry point app — bắt đầu từ đây
├── test/
│   └── widget_test.dart   # Widget tests
├── ios/                   # iOS native project (mở Xcode được)
├── android/               # Android native project (mở Android Studio được)
├── macos/                 # macOS native
├── web/                   # Web (index.html, manifest)
├── pubspec.yaml           # Manifest — deps, asset, font, version
├── pubspec.lock           # Resolved deps (commit vào git)
├── analysis_options.yaml  # Lint rules
└── .gitignore

pubspec.yaml Flutter — khác Dart console

name: my_app
description: A new Flutter project.
publish_to: 'none'
version: 1.0.0+1   # 1.0.0 (versionName) + 1 (versionCode)

environment:
  sdk: ^3.3.0
  flutter: ">=3.22.0"

dependencies:
  flutter:
    sdk: flutter        # Flutter framework (đặc biệt — không từ pub.dev)
  cupertino_icons: ^1.0.6

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^4.0.0

flutter:
  uses-material-design: true
  assets:
    - assets/images/
    - assets/data/
  fonts:
    - family: Inter
      fonts:
        - asset: assets/fonts/Inter-Regular.ttf
        - asset: assets/fonts/Inter-Bold.ttf
          weight: 700

Khác Dart console:

  • Section flutter: ở dưới — declare asset, font, plugin config.
  • flutter: sdk: flutter — special syntax, không phải package pub.dev.
  • Version 1.0.0+1 — Flutter convention: name+code.

8. Chạy app

# List device available
flutter devices

# Output:
# 3 connected devices:
# iPhone 15 (mobile) •  • ios          • iOS 17.0
# sdk gphone64 arm64 (mobile) •  • android-arm64
# Chrome (web) • chrome • web-javascript

# Chạy default (chọn device đầu tiên)
flutter run

# Chạy device cụ thể
flutter run -d chrome
flutter run -d "iPhone 15"
flutter run -d macos
💡 Multi-device cùng lúc

Plugin Flutter cho VS Code có "Run on multiple devices" — chạy cùng app trên iOS + Android cùng lúc, hot reload cả 2. Test UI consistency cross-platform cực nhanh.

9. Hot reload vs Hot restart vs Full rebuild

Hot ReloadHot RestartFull Rebuild
Triggerr trong terminal, save file (VS Code)R (Shift+R)q + flutter run lại
Thời gian~200ms~1s~30s+
Giữ state?Không (reset)Không
Apply gì?Widget tree rebuildRerun main()Recompile + rebuild native
Khi nào dùngSửa widget, color, paddingĐổi global state, enum, top-level varĐổi native code, asset, font, pubspec
🧠 Khi nào hot reload không work?
  • Đổi main() function.
  • Đổi initState() body (state đã init xong, không re-run).
  • Thêm/xoá field của class (vì existing instance không có field mới).
  • Đổi enum, type definition.
  • Đổi global variable / static field.

Khi gặp issue → thử Hot Restart (R). Vẫn không work → Full Rebuild.

10. Build mode — Debug / Profile / Release

DebugProfileRelease
ModeJITAOTAOT
Hot reloadKhôngKhông
AssertionBậtBậtTắt
DevToolsFullPerformance onlyKhông
PerformanceChậm (debug overhead)Gần productionProduction
Khi dùngPhát triểnĐo performanceShip cho user
Lệnhflutter runflutter run --profileflutter build apk --release
⚠️ Đo performance trên Debug = sai

Debug mode chậm hơn release ~10-100x do JIT + debug overhead. Luôn đo trên Profile hoặc Release. Đừng bao giờ optimize dựa trên Debug benchmark.

11. DevTools — sneak peek

Khi chạy flutter run, terminal in URL DevTools:

The Flutter DevTools debugger and profiler on iPhone 15 is available at:
http://127.0.0.1:9100?uri=http://127.0.0.1:60001/abc123

Mở URL → DevTools UI với 6 tab chính:

  • Widget Inspector — explore widget tree.
  • Performance — record CPU, flame chart.
  • Memory — heap snapshot, leak detection.
  • Network — log HTTP request.
  • Logging — log filter.
  • App Size — bundle analysis.

Sẽ deep dive ở chương 15.

12. Bài tập

Cài Flutter qua FVM + screenshot doctor

Cài Flutter qua FVM (theo section 2). Chạy flutter doctor -v. Screenshot output. Verify mọi check [✓], không có [!].

💡 Gợi ý đáp án

Nếu có warning, áp dụng bảng troubleshoot section 5. Common fix:

  • iOS warning → cài Xcode, accept license, install CocoaPods.
  • Android warning → cài Android Studio + SDK Platform, accept licenses.
  • Chrome warning → cài Chrome browser.

Chạy app trên 3 device

Tạo project flutter create it_basic_demo. Chạy trên 3 device: iOS Simulator, Android Emulator, Chrome. Screenshot mỗi device.

💡 Gợi ý đáp án
cd it_basic_demo

# Terminal 1: iOS
open -a Simulator
flutter run -d "iPhone 15"

# Terminal 2: Android
emulator -avd Pixel_7  # tên AVD
flutter run -d emulator-5554

# Terminal 3: Chrome
flutter run -d chrome

So sánh visual: cùng code, nhưng button có thể ripple effect khác nhau (Material vs Cupertino). Chương 4 sẽ học.

Đổi tên hiển thị app + hot reload

Sửa lib/main.dart: đổi 'Flutter Demo Home Page' thành tên bạn. Hot reload (save file hoặc nhấn r). Screenshot. Sau đó đổi 'You have pushed the button this many times' thành tiếng Việt. Hot reload.

💡 Gợi ý đáp án
// lib/main.dart
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;
  ...
}

// Trong MaterialApp:
home: const MyHomePage(title: 'Việt Nguyễn'),  // thay vì 'Flutter Demo Home Page'

// Counter:
const Text('Bạn đã nhấn nút này nhiêu lần:'),

Hot reload trigger trong VS Code: Cmd+S save file. Hoặc trong terminal: r.

Add package + pub get

Add 2 package: flutter_svghttp. Edit pubspec.yaml manually + chạy flutter pub get. Check pubspec.lock — đếm số resolved package.

💡 Gợi ý đáp án
dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.6
  flutter_svg: ^2.0.10
  http: ^1.2.0
flutter pub get
# Hoặc shorthand:
# flutter pub add flutter_svg http

cat pubspec.lock | grep -c '^\s*[a-z_]*:$'
# Hoặc xem tree
flutter pub deps

Mở project trong Xcode + đổi Display Name

Mở iOS project trong Xcode: open ios/Runner.xcworkspace. Trong Runner target → Info.plist, đổi Bundle display name thành "Hello VN". Rebuild app → home screen iOS hiển thị tên mới.

💡 Gợi ý đáp án

Trong Info.plist tìm key CFBundleDisplayName. Nếu không có, thêm:

<key>CFBundleDisplayName</key>
<string>Hello VN</string>

Sau đó flutter run -d "iPhone 15" để rebuild. Hot reload không apply native config change.

13. Quiz

Q1

flutter doctor báo [!] Xcode - develop for iOS — nguyên nhân phổ biến?

Xem đáp án

Đáp án: Xcode chưa accept license hoặc thiếu CocoaPods. Fix: sudo xcodebuild -license accept + sudo gem install cocoapods.

Q2

Hot reload không apply được change — chuyện gì thường xảy ra?

Xem đáp án

Đáp án: Đổi main(), initState(), enum, global state, hoặc thêm/xoá field class. Cần Hot Restart (R).

Q3

flutter create mặc định include platforms nào?

Xem đáp án

Đáp án: Tất cả nếu đã enable: iOS, Android, Web, macOS, Linux, Windows. Có thể giới hạn với --platforms=ios,android.

Q4

FVM khác cài Flutter raw ở điểm chính nào?

Xem đáp án

Đáp án: FVM cho phép cài nhiều version cùng lúc + switch per project (qua .fvmrc). Raw chỉ 1 version global.

Q5

Mode release chạy được hot reload không?

Xem đáp án

Đáp án: Không. Hot reload chỉ Debug mode (JIT). Release là AOT compile, code đã native, không thể swap runtime.

Q6

pubspec.yaml declare assets: [assets/images/] — Flutter biết file gì?

Xem đáp án

Đáp án: Folder kết thúc / → Flutter include tất cả file trong folder. File cụ thể (vd assets/img/logo.png) → chỉ file đó.

Q7

iOS app có thể dùng flutter pub get thay pod install không?

Xem đáp án

Đáp án: Không hoàn toàn. flutter pub get resolve Dart deps. iOS native deps (CocoaPods) cần cd ios && pod install. Flutter thường tự gọi sau pub get.

Q8

flutter run không thấy device nào — đầu tiên check gì?

Xem đáp án

Đáp án: flutter doctor trước, sau đó flutter devices. Cần: Simulator/Emulator mở, hoặc USB device với debugging enable.

14. Tổng kết

  • ✅ Flutter = framework UI cross-platform, render engine riêng (Skia/Impeller).
  • ✅ 3 layer: Framework (Dart) / Engine (C++) / Embedder (platform).
  • ✅ Cài qua FVM — multi-version support.
  • ✅ iOS toolchain: Xcode + CocoaPods. Android toolchain: Android Studio + SDK + AVD.
  • flutter doctor phải sạch trước khi học tiếp.
  • flutter create sinh project structure đa platform.
  • pubspec.yaml Flutter có section flutter: riêng cho asset/font.
  • ✅ Hot reload (200ms, giữ state) vs Hot restart (1s, reset) vs Full rebuild (30s+).
  • ✅ 3 build mode: Debug (JIT) / Profile (AOT, đo perf) / Release (AOT, ship).

15. Tiếp theo