Flutter คืออะไร
Flutter คือ Framework โอเพนซอร์สที่พัฒนาโดย Google สำหรับสร้างแอปพลิเคชันข้ามแพลตฟอร์ม (Cross-platform) ด้วยโค้ดชุดเดียว ใช้ภาษา Dart ในการเขียน จุดเด่นคือสามารถเขียนโค้ดครั้งเดียว แล้วนำไปใช้ได้ทั้งบน iOS และ Android โดยไม่ต้องแยกทีมเขียนสองภาษา
บทความนี้ไม่ใช่แค่ทฤษฎี แต่เป็น Workshop แบบลงมือทำ — เราจะสร้างแอป Todo List ตัวจริงไปด้วยกันทีละขั้นตอน ตั้งแต่ศูนย์จนถึงระดับที่นำไปใช้งานจริงได้ อ่านแล้วเปิด Editor ทำตามได้เลย
สิ่งที่จะได้หลังจบ Workshop นี้
- แอป Todo List ที่เพิ่ม ลบ และติ๊กงานว่าเสร็จแล้วได้
- เข้าใจ Widget, State และการจัดการข้อมูลใน Flutter จากของจริง ไม่ใช่แค่ทฤษฎี
- รู้วิธีบันทึกข้อมูลให้อยู่ถาวรแม้ปิดแอป
- รู้วิธีขยับจาก
setStateพื้นฐานไปสู่ State Management ระดับโปรด้วย Provider
Step 0: เตรียมเครื่องมือ (Basic)
- ติดตั้ง Flutter SDK จาก flutter.dev แล้วตั้งค่า Path ให้เรียกคำสั่ง
flutterจาก Terminal ได้ - ติดตั้ง Android Studio หรือ VS Code พร้อมปลั๊กอิน Flutter และ Dart
- เปิด Terminal แล้วรันคำสั่งนี้เพื่อเช็กว่าเครื่องมือครบ:
flutter doctor
ถ้าเห็นเครื่องหมายถูกสีเขียวส่วนใหญ่ แปลว่าพร้อมลงมือทำต่อได้เลย
Step 1: สร้างโปรเจกต์แรก (Basic)
รันคำสั่งนี้ใน Terminal เพื่อสร้างโปรเจกต์ใหม่ชื่อ todo_app:
flutter create todo_app
cd todo_app
flutter run
ถ้าทุกอย่างถูกต้อง จะเห็นแอปตัวอย่าง “Counter” รันขึ้นมาบนเครื่องจำลองหรืออุปกรณ์ของคุณ ต่อไปเราจะเริ่มแก้ไฟล์ lib/main.dart ให้กลายเป็นแอป Todo List
Step 2: สร้างหน้าจอแสดงรายการงาน (Basic)
เปิดไฟล์ lib/main.dart แล้วแทนที่โค้ดทั้งหมดด้วยโค้ดนี้ เพื่อสร้างโครงหน้าจอและ Widget พื้นฐาน (Scaffold, AppBar, ListView):
import 'package:flutter/material.dart';
void main() {
runApp(const TodoApp());
}
class TodoApp extends StatelessWidget {
const TodoApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Todo List',
home: const TodoHomePage(),
);
}
}
class TodoHomePage extends StatelessWidget {
const TodoHomePage({super.key});
@override
Widget build(BuildContext context) {
final items = ['ซื้อของเข้าบ้าน', 'อ่านหนังสือ Flutter', 'ออกกำลังกาย'];
return Scaffold(
appBar: AppBar(title: const Text('Todo List ของฉัน')),
body: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
leading: const Icon(Icons.check_box_outline_blank),
title: Text(items[index]),
);
},
),
);
}
}
บันทึกไฟล์แล้วกด Hot Reload (หรือรัน flutter run ใหม่) จะเห็นรายการงานสามอย่างแสดงบนหน้าจอ นี่คือการใช้ ListView.builder ร่วมกับ ListTile ซึ่งเป็น Widget พื้นฐานที่สุดสำหรับแสดงรายการข้อมูล
Step 3: เพิ่ม/ลบ/ติ๊กงานด้วย State (Intermediate)
ตอนนี้ข้อมูลยังเป็นค่าคงที่ ขั้นตอนนี้เราจะเปลี่ยน TodoHomePage ให้เป็น StatefulWidget เพื่อให้เพิ่ม ลบ และติ๊กงานว่าเสร็จได้จริง แทนที่โค้ดทั้งไฟล์ด้วยเวอร์ชันนี้:
import 'package:flutter/material.dart';
void main() {
runApp(const TodoApp());
}
class TodoApp extends StatelessWidget {
const TodoApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Todo List',
home: const TodoHomePage(),
);
}
}
class Todo {
Todo(this.title, {this.done = false});
String title;
bool done;
}
class TodoHomePage extends StatefulWidget {
const TodoHomePage({super.key});
@override
State createState() => _TodoHomePageState();
}
class _TodoHomePageState extends State {
final List _todos = [
Todo('ซื้อของเข้าบ้าน'),
Todo('อ่านหนังสือ Flutter'),
Todo('ออกกำลังกาย'),
];
final _controller = TextEditingController();
void _addTodo() {
if (_controller.text.trim().isEmpty) return;
setState(() {
_todos.add(Todo(_controller.text.trim()));
_controller.clear();
});
}
void _toggleDone(int index) {
setState(() {
_todos[index].done = !_todos[index].done;
});
}
void _removeTodo(int index) {
setState(() {
_todos.removeAt(index);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Todo List ของฉัน')),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(12),
child: Row(
children: [
Expanded(
child: TextField(
controller: _controller,
decoration: const InputDecoration(
hintText: 'เพิ่มงานใหม่...',
),
),
),
IconButton(
icon: const Icon(Icons.add),
onPressed: _addTodo,
),
],
),
),
Expanded(
child: ListView.builder(
itemCount: _todos.length,
itemBuilder: (context, index) {
final todo = _todos[index];
return ListTile(
leading: Checkbox(
value: todo.done,
onChanged: (_) => _toggleDone(index),
),
title: Text(
todo.title,
style: TextStyle(
decoration: todo.done
? TextDecoration.lineThrough
: TextDecoration.none,
),
),
trailing: IconButton(
icon: const Icon(Icons.delete_outline),
onPressed: () => _removeTodo(index),
),
);
},
),
),
],
),
);
}
}
ลองพิมพ์ข้อความในช่องแล้วกดปุ่ม + ดู งานใหม่จะเพิ่มเข้าไปในรายการทันที เพราะทุกครั้งที่เรียก setState Flutter จะสั่งวาดหน้าจอใหม่โดยอัตโนมัติ นี่คือหัวใจของการจัดการ State แบบพื้นฐาน
Step 4: บันทึกข้อมูลให้อยู่ถาวร (Intermediate → Advanced)
ตอนนี้ถ้าปิดแอป รายการงานจะหายหมด ขั้นตอนนี้เราจะใช้แพ็กเกจ shared_preferences เพื่อบันทึกข้อมูลลงเครื่อง เริ่มจากติดตั้งแพ็กเกจ:
flutter pub add shared_preferences
จากนั้นเพิ่มฟังก์ชันโหลดและบันทึกข้อมูลใน _TodoHomePageState:
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
Future _loadTodos() async {
final prefs = await SharedPreferences.getInstance();
final raw = prefs.getString('todos');
if (raw == null) return;
final list = jsonDecode(raw) as List;
setState(() {
_todos
..clear()
..addAll(list.map((e) => Todo(e['title'], done: e['done'])));
});
}
Future _saveTodos() async {
final prefs = await SharedPreferences.getInstance();
final raw = jsonEncode(
_todos.map((t) => {'title': t.title, 'done': t.done}).toList(),
);
await prefs.setString('todos', raw);
}
เรียก _loadTodos() ใน initState() และเรียก _saveTodos() ทุกครั้งหลัง setState ในฟังก์ชัน _addTodo, _toggleDone และ _removeTodo ปิดแอปแล้วเปิดใหม่ ข้อมูลจะยังอยู่ครบ
Step 5: ยกระดับสู่ Provider (Advanced)
เมื่อแอปโตขึ้น การใส่ Logic ทั้งหมดไว้ใน Widget เดียวจะดูแลยาก ขั้นตอนนี้เราจะแยก Logic ออกมาด้วย provider เริ่มจากติดตั้ง:
flutter pub add provider
สร้างไฟล์ lib/todo_provider.dart เพื่อย้าย State และ Logic ออกจากหน้าจอ:
import 'package:flutter/material.dart';
class Todo {
Todo(this.title, {this.done = false});
String title;
bool done;
}
class TodoProvider extends ChangeNotifier {
final List _todos = [];
List get todos => _todos;
void add(String title) {
if (title.trim().isEmpty) return;
_todos.add(Todo(title.trim()));
notifyListeners();
}
void toggle(int index) {
_todos[index].done = !_todos[index].done;
notifyListeners();
}
void remove(int index) {
_todos.removeAt(index);
notifyListeners();
}
}
จากนั้นครอบแอปด้วย ChangeNotifierProvider ใน main() และเปลี่ยนหน้าจอให้อ่านข้อมูลผ่าน context.watch<TodoProvider>() แทนการเก็บ State ไว้เองใน Widget จุดสำคัญคือ UI จะไม่ต้องรู้เรื่อง Logic การเพิ่ม/ลบ/บันทึกข้อมูลอีกต่อไป ทำให้แยกทดสอบและดูแลรักษาได้ง่ายขึ้นมาก ซึ่งเป็นแนวคิดเดียวกับที่ใช้ในแอป Production จริง
Step 6: รันและทดสอบบนอุปกรณ์จริง
- เชื่อมต่อโทรศัพท์ผ่าน USB หรือเปิด Emulator/Simulator แล้วรัน
flutter run - ลองเพิ่ม ลบ และติ๊กงานหลายๆ รายการ เพื่อดูว่า State อัปเดตถูกต้องทุกจุด
- ปิดแอปแล้วเปิดใหม่ เพื่อยืนยันว่าข้อมูลจาก Step 4 ยังอยู่ครบ
- ลองเขียน Widget Test ง่ายๆ ด้วย
flutter testเพื่อเช็กว่าเพิ่มงานแล้วรายการยาวขึ้นจริง
วิดีโอสอน Flutter ฉบับเต็ม
สำหรับใครที่อยากดูภาพรวมการเขียน Flutter แบบละเอียดเพิ่มเติมนอกเหนือจาก Workshop นี้ แนะนำวิดีโอคอร์สสอน Flutter สำหรับผู้เริ่มต้นแบบเต็ม ครอบคลุมตั้งแต่การติดตั้งเครื่องมือไปจนถึงการสร้างแอปจริง
สรุป Roadmap ที่เพิ่งทำผ่านไป
- ติดตั้งเครื่องมือและสร้างโปรเจกต์แรกด้วย
flutter create - สร้าง UI แสดงรายการด้วย Widget พื้นฐาน เช่น ListView และ ListTile
- เพิ่มการโต้ตอบด้วย StatefulWidget และ
setState - บันทึกข้อมูลถาวรด้วย
shared_preferences - แยก Logic ออกจาก UI ด้วย Provider เพื่อความพร้อมสู่ Production
- ทดสอบบนอุปกรณ์จริงและเขียน Test เบื้องต้น
Flutter เหมาะกับใคร
เหมาะทั้งกับผู้เริ่มต้นที่อยากทำแอปของตัวเองให้เสร็จเร็ว และกับทีมพัฒนาในองค์กรที่ต้องการลดต้นทุนดูแลแอปสองแพลตฟอร์ม รวมถึง Web Developer ที่มีพื้นฐาน JavaScript หรือ TypeScript อยู่แล้ว เพราะแนวคิดเรื่อง Component/Widget และการจัดการ State นั้นคล้ายกับ React มาก ทำให้เรียนรู้ต่อยอดได้ไม่ยาก
สรุป
จาก Workshop นี้จะเห็นว่า Flutter ไม่ใช่แค่ทฤษฎี แต่ลงมือทำตามได้จริงตั้งแต่บรรทัดแรกจนถึงแอปที่บันทึกข้อมูลได้และมีโครงสร้างพร้อมขยาย เริ่มจาก Widget ง่ายๆ ต่อด้วยการจัดการ State และปิดท้ายด้วยแนวคิดที่ใช้ในโปรเจกต์ระดับ Production จริง หากกำลังมองหาสายอาชีพ Mobile Developer หรืออยากสร้างแอปของตัวเอง Flutter คือจุดเริ่มต้นที่คุ้มค่าต่อการลงทุนเวลาในปี 2025 นี้