Flutter
Framework สำหรับสร้างแอป cross-platform โดย Google เขียนด้วยภาษา Dart ตัวเดียวแล้วรันได้ทั้ง Android, iOS, Web, Desktop
จุดเด่น
- ไม่ใช่ภาษาโปรแกรมมิ่ง — เป็น framework ที่ใช้ภาษา Dart
- Compile เป็น native ARM machine code โดยตรง (ไม่ผ่าน interpreter หรือ bridge)
- ทุกอย่างใน Flutter คือ Widgets — เป็น building blocks ของ UI ทั้งหมด
- เขียนโค้ด Dart ตัวเดียว → ได้ทั้ง iOS, Android, Web, Desktop
แพลตฟอร์มที่รองรับ
| แพลตฟอร์ม | สถานะ | หมายเหตุ |
|---|---|---|
| iOS & Android | หลัก | รองรับดีที่สุด |
| Web | รอง | ใช้ features ของ modern browser |
| Windows, macOS, Linux | รอง | Desktop apps |
ข้อจำกัด: iOS/macOS apps → build ได้บน macOS เท่านั้น (ต้องลง Xcode) / Android/Web → build ได้บน ทุก OS
Flutter App เริ่มทำงานยังไง
graph LR A["main()"] -->|"Dart เรียกอัตโนมัติ"| B["runApp()"] B -->|"สั่ง Flutter เริ่ม render"| C[Widget Tree] C --> D[แสดงผลบนจอ]
void main() {
runApp(
MaterialApp(
home: Scaffold(
body: Center(
child: Text("สวัสดี"),
),
),
),
);
}| Concept | หน้าที่ | เทียบ Java/Spring |
|---|---|---|
main() | จุดเริ่มต้นโปรแกรม | public static void main() |
runApp() | สั่ง Flutter เริ่ม render Widget Tree | SpringApplication.run() |
MaterialApp | Widget ราก ให้ Material Design theme | @SpringBootApplication |
Scaffold | โครงร่างหน้าจอ (body, appBar, drawer) | HTML <body> |
โครงสร้างโปรเจกต์
my_app/
├── lib/ ← โค้ด Dart ทั้งหมดอยู่ที่นี่
│ └── main.dart ← entry point
├── android/ ios/ web/ ← ไฟล์เฉพาะ platform (Flutter จัดการให้)
├── build/ ← ไฟล์ที่ Flutter สร้างตอน compile (อย่าแก้)
├── test/ ← Automated tests
├── assets/images/ ← รูปภาพ (ลงทะเบียนใน pubspec.yaml)
├── pubspec.yaml ← จัดการ dependencies + assets ← สำคัญ!
└── analysis_options.yaml ← ตั้งค่า linting/code style
Best practice: 1 widget = 1 ไฟล์ ตั้งชื่อแบบ snake_case
Flutter vs Ionic
| ด้าน | Flutter | Ionic |
|---|---|---|
| ภาษา | Dart | HTML/CSS/JavaScript |
| การแสดงผล | Compile เป็น native | WebView (เหมือนเปิดเว็บในแอป) |
| ความเร็ว | เร็ว (native) | ช้ากว่า (WebView overhead) |
| เปรียบเทียบ | พูดเกาหลีกับคนเกาหลีตรงๆ | พูดอังกฤษแล้วมีล่ามแปลให้ |
Widget Lifecycle
3 lifecycle methods สำคัญของ StatefulWidget:
graph LR A["initState()"] -->|"ครั้งเดียวตอนสร้าง"| B["build()"] B -->|"ทุกครั้งที่ setState()"| B B -->|"ก่อน widget ถูกลบ"| C["dispose()"]
class _MyState extends State<MyWidget> {
@override
void initState() { // 1. ทำงานครั้งเดียวตอนสร้าง State
super.initState();
}
@override
Widget build(BuildContext context) { // 2. ทำงานตอนสร้าง UI + ทุกครั้งที่ setState()
return Container();
}
@override
void dispose() { // 3. ทำงานก่อน widget ถูกลบ (cleanup)
super.dispose();
}
}Theming — กำหนด style ทั้งแอปจากจุดเดียว
MaterialApp(
theme: ThemeData().copyWith(
colorScheme: ColorScheme.fromSeed(
seedColor: const Color.fromARGB(255, 96, 59, 181),
),
appBarTheme: const AppBarTheme(backgroundColor: ...),
cardTheme: const CardThemeData(margin: ...),
textTheme: ThemeData().textTheme.copyWith(
titleLarge: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
),
darkTheme: darkTheme, // Dark mode theme
themeMode: ThemeMode.system, // ตาม setting ของ device
);
// ใช้ใน widget:
Theme.of(context).colorScheme.primaryDebugging
3 เครื่องมือหลัก ใช้คนละจังหวะ: Error Messages ตอนแอปพัง, Debug Mode ตอนไล่ logic, DevTools ตอนปรับ UI
1. Error Messages — อ่าน error เพื่อหาจุดเริ่มต้น
- error บนจอแอปเห็น เฉพาะตอน development — production แอปจะ crash เฉยๆ
- เปิด Debug Console (
View → Appearance → Panel) เพื่อดูรายละเอียดเพิ่ม - เลื่อนขึ้น ใน Debug Console เสมอ — error จริงอยู่ข้างบนของ stack trace
- stack trace ส่วนใหญ่เป็น internal ของ Flutter → ข้ามได้ → มองหา บรรทัดที่ highlight → นั่นคือโค้ดของเรา
- คลิก link ใน stack trace → กระโดดไปบรรทัดที่มีปัญหาได้เลย
2. Debug Mode (F5) — หยุดโค้ดแล้วตรวจค่า
เริ่มแอปด้วย Start Debugging (F5) แทน Run Without Debugging — แอปช้าลงนิดแต่ปลดล็อค debugging features
| Feature | วิธีใช้ | ทำอะไร |
|---|---|---|
| Breakpoint | คลิกจุดแดงซ้าย line number | หยุดแอปตรงบรรทัดนั้น |
| Hover | เลื่อน mouse ไปเหนือตัวแปร | ดูค่าปัจจุบัน + expand object ได้ |
| Watch | คลิกขวาตัวแปร → Add to Watch | ติดตามค่าตลอดโดยไม่ต้อง hover |
| Step Over | ปุ่มที่ 2 บน toolbar | เดินโค้ดทีละบรรทัด |
| Resume | ปุ่ม play | ให้แอปรันต่อจนถึง breakpoint ถัดไป |
| Call Stack | panel ด้านซ้าย | ดูว่า method ไหนเรียก method ไหน |
| Variables | panel ด้านซ้าย | ดู this, context, properties ทั้งหมด |
3. Flutter DevTools — ตรวจ UI + Performance
เปิด: Ctrl+Shift+P → “Flutter DevTools” → Open DevTools in Web Browser
| Page | ใช้ทำอะไร |
|---|---|
| Flutter Inspector | ดู widget tree, ปรับ layout, ตรวจ properties |
| Performance | วัด performance (ใช้ Profile mode ไม่ใช่ Debug) |
| Network | ดู HTTP requests ที่แอปส่ง |
| Logging | ดู log messages + errors |
| App Size | วิเคราะห์ขนาดแอป |
Flutter Inspector ทำอะไรได้:
- Widget Tree — เห็น UI ทั้งหมดเป็น tree ซ้อนกัน เลือกดูแต่ละ widget
- Layout Explorer — เห็น width/height + ถ้าเลือก Column/Row ปรับ alignment ได้ realtime ผ่าน dropdown
- Widget Details Tree — ดู properties ทุกตัว (text, color, size)
- Select Widget Mode — คลิก widget บนจอแอปตรงๆ → กระโดดไปหาใน tree
- Guidelines — แสดงเส้น guide ว่าทำไม widget อยู่ตำแหน่งนั้น
- Highlight Oversized Images — เตือนถ้ารูปใหญ่เกินจำเป็น (เปลือง memory)
Responsive & Adaptive
Responsive — ปรับ layout ตามขนาดจอ
final width = MediaQuery.of(context).size.width;
if (width < 600) {
return Column(children: [chart, expensesList]); // มือถือแนวตั้ง
} else {
return Row(children: [
Expanded(child: chart),
Expanded(child: expensesList),
]); // แนวนอน/tablet
}ดูเพิ่มเติม: Responsive Design
Adaptive — ปรับ widget ตาม platform
import 'dart:io';
if (Platform.isIOS) { /* ใช้ Cupertino widgets */ }
if (Platform.isAndroid) { /* ใช้ Material widgets */ }Flutter Internals — Three Trees
graph LR A["Widget Tree<br/>โค้ดที่เราเขียน<br/>immutable สร้างใหม่บ่อย"] --> B["Element Tree<br/>Flutter จัดการ<br/>จับคู่ widget กับ render"] B --> C["Render Tree<br/>วาดจริงบนจอ<br/>แก้เฉพาะส่วนที่เปลี่ยน"]
เมื่อ setState() → สร้าง Widget Tree ใหม่ แต่ reuse Element + Render Tree เท่าที่ทำได้ → ประหยัด performance
ตัวอย่าง: แอปจากคอร์ส
แต่ละแอปมีหน้าแยก — สรุปสิ่งที่เรียน, widget tree (Mermaid), code ตัวอย่าง:
- Dice Roller App — Section 1-2: StatefulWidget, setState, Widget Tree
- Quiz App — Section 3: Conditional rendering, Lifting State Up, data models
- Expense Tracker App — Section 5-6: AppBar, Modal, Theme, Responsive, ListView
แอปที่สร้างในคอร์ส
| แอป | Section | Concepts หลัก |
|---|---|---|
| Dice Roller App | 1-2 | StatefulWidget, setState, Widget Tree |
| Quiz App | 3 | Conditional rendering, Lifting State Up, data models |
| Expense Tracker App | 5-6 | AppBar, Modal, Theme, Responsive Design, ListView |
| TODO App | 7 | Three Trees, Keys |
| Meals App | 8-10 | Navigation, Riverpod, Animation |
| Shopping List | 11-12 | Form, HTTP, FutureBuilder, Firebase |
| Favorite Places | 13 | Camera, Google Maps, SQLite |
| Chat App | 14 | Firebase Auth, Firestore, Push Notifications |
Key Points
- Flutter compile Dart เป็น native ARM machine code → performance ดี
- ทุกอย่างบนจอคือ Widgets ซ้อนกันเป็น Widget Tree
setState()คือหัวใจของ UI update — บอก Flutter ว่า state เปลี่ยนแล้ว ให้เรียกbuild()ใหม่constช่วยประหยัด memory — Dart สร้าง object ก้อนเดียวใช้ร่วมกัน- Theme กำหนดจากจุดเดียว (
ThemeData) ใช้ได้ทั้งแอป - Three Trees ทำให้ Flutter rebuild เฉพาะส่วนที่เปลี่ยน → ประหยัด performance
- แอปที่ซับซ้อนต้องใช้ State Management (เช่น Riverpod) แทนการส่ง state ผ่าน constructor
Related
- Dart — ภาษาที่ Flutter ใช้
- Widgets — building blocks ของ UI
- Navigation — ระบบเปลี่ยนหน้าจอ
- State Management — จัดการ state ข้าม widgets
- Riverpod — state management library
- Firebase — backend service
- Animation — สร้าง animation ใน Flutter
- Responsive Design — ปรับ UI ตามขนาดจอ
- Three Trees — Widget/Element/Render tree internals
- Framework — Flutter เป็น UI framework
- Ionic — ทางเลือกแบบ WebView
- OOP — Flutter/Dart ใช้แนวคิด OOP เต็มรูปแบบ
- Quartz — SSG ที่ใช้ deploy Digital Garden เก็บ notes เรื่อง Flutter