Three Trees
Flutter ใช้ 3 trees ทำงานภายใน — เข้าใจสิ่งนี้ทำให้เข้าใจว่าทำไม setState() ถึงเร็ว และทำไม Keys ถึงสำคัญ
3 Trees คืออะไร
Widget Tree Element Tree Render Tree
(โค้ดที่เราเขียน) (Flutter จัดการ) (วาดจริงบนจอ)
1. Widget Tree — สิ่งที่เราเขียน
- Immutable — ถูกสร้างใหม่ทุกครั้งที่
setState() - เป็นแค่ configuration/blueprint บอกว่า UI ควรหน้าตายังไง
- ถูก (cheap) ในการสร้าง — Flutter ออกแบบให้สร้างใหม่ได้บ่อยๆ
2. Element Tree — ตัวกลาง
- Flutter จัดการเอง — ไม่ถูกสร้างใหม่ ทุกครั้ง
- จับคู่ (match) Widget กับ Render Object
- เมื่อ Widget Tree สร้างใหม่ → Element Tree เปรียบเทียบ กับ Widget ใหม่ แล้วอัปเดตเฉพาะส่วนที่เปลี่ยน
3. Render Tree — สิ่งที่วาดจริง
- วาด pixel จริงบนหน้าจอ
- แก้เฉพาะส่วนที่เปลี่ยน — ไม่ redraw ทั้งจอ
- แพง (expensive) ในการสร้าง — Flutter จึง reuse ให้มากที่สุด
Flow เมื่อ setState()
setState() ถูกเรียก
↓
Widget Tree สร้างใหม่ทั้งต้น (ราคาถูก)
↓
Element Tree เปรียบเทียบ Widget ใหม่ กับ Widget เก่า
↓
ส่วนที่เหมือนกัน → reuse Element + Render Object เดิม
ส่วนที่ต่าง → อัปเดต Render Object
↓
จอแสดงผลเฉพาะส่วนที่เปลี่ยน
ผลลัพธ์: แม้ build() จะทำงานบ่อย แต่จอจริงอัปเดตแค่ส่วนน้อย → เร็ว
Keys — ช่วย Element Tree จับคู่ถูกต้อง
เมื่อ list items สลับตำแหน่ง/เพิ่ม/ลบ → Element Tree อาจจับคู่ Widget กับ Element ผิดตัว:
ก่อนลบ item: หลังลบ item (ไม่มี Key):
Widget A → Element A Widget B → Element A ❌ ผิด!
Widget B → Element B Widget C → Element B ❌ ผิด!
Widget C → Element C (Element C ถูกลบ)
แก้ด้วย Key
ListView(
children: items.map((item) =>
TodoItem(
key: ValueKey(item.id), // ← Key ช่วยจับคู่ถูกต้อง
item: item,
),
).toList(),
);หลังลบ item (มี Key):
Widget B → Element B ✅ ถูก! (จับคู่ตาม key)
Widget C → Element C ✅ ถูก!
(Element A ถูกลบ)
เมื่อไหร่ต้องใส่ Key
- StatefulWidget ใน list ที่มีการเพิ่ม/ลบ/เรียงใหม่ → ต้องใส่
- StatelessWidget ใน list → ไม่จำเป็น (ไม่มี state ให้สับสน)
- Widget ที่ไม่อยู่ใน list → ไม่จำเป็น
var vs final vs const (มุมมอง Performance)
var | final | const | |
|---|---|---|---|
| Widget Tree | สร้างใหม่ทุกครั้ง | สร้างใหม่ทุกครั้ง | สร้างครั้งเดียว reuse |
| Performance | ปกติ | ปกติ | ดีที่สุด |
const widget ไม่ถูกสร้างใหม่เมื่อ setState() → ประหยัดทั้ง memory และ CPU
Key Points
- Flutter ใช้ 3 trees: Widget (blueprint), Element (ตัวกลาง), Render (วาดจริง)
setState()สร้าง Widget Tree ใหม่ แต่ reuse Element + Render Tree → เร็ว- Keys ช่วย Element Tree จับคู่ Widget ถูกตัวเมื่อ list เปลี่ยน
constwidgets ถูก reuse โดยสมบูรณ์ → performance ดีที่สุด
Related
- Flutter — framework ที่ใช้ Three Trees
- Widgets — Widget Tree คือ tree ของ Widgets
- State Management — setState triggers Widget Tree rebuild