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)

varfinalconst
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 เปลี่ยน
  • const widgets ถูก reuse โดยสมบูรณ์ → performance ดีที่สุด
  • Flutter — framework ที่ใช้ Three Trees
  • Widgets — Widget Tree คือ tree ของ Widgets
  • State Management — setState triggers Widget Tree rebuild