Element Tree: คืออะไร ความสัมพันธ์กับ RenderObject และหลักการทำงาน

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-07-01 เวลาอ่าน: 10 นาที

Element Tree คือเลเยอร์กลางใน Flutter ที่เชื่อมต่อ Widget Tree แบบประกาศกับ RenderObject Tree แบบคำสั่ง แตกต่างจาก widget ที่ถูกสร้างใหม่ทุกครั้งที่มีการ rebuild องค์ประกอบจะคงอยู่ระหว่างการอัปเดตและจัดการสถานะ คีย์ และวงจรชีวิต ตาม Flutter API Reference, 2025 การทำความเข้าใจ Element Tree เป็นสิ่งจำเป็นสำหรับการทำงานกับคีย์อย่างมีประสิทธิภาพ การเพิ่มประสิทธิภาพ และการดีบักพฤติกรรมที่ไม่คาดคิดของ widget

ประเด็นสำคัญ

  • Element Tree — เลเยอร์ถาวรระหว่าง Widget และ RenderObject Tree ที่คงอยู่ระหว่างการสร้างใหม่
  • แต่ละ widget สร้างองค์ประกอบที่จัดการการแทรกในทรีและวงจรชีวิต
  • StatefulElement เก็บออบเจ็กต์ State ที่ยังคงเข้าถึงได้แม้หลังจากสร้าง widget ใหม่
  • คีย์ (Key) ทำงานที่ระดับ Element Tree ช่วยในการจับคู่ widget ระหว่างการสร้างใหม่
  • Element Tree เชื่อมต่อโดยตรงกับ RenderObject Tree — แต่ละองค์ประกอบสามารถสร้างหรือลบ RenderObject ได้

Element Tree ใน Flutter คืออะไร?

Element Tree คือลำดับชั้นกลางใน Flutter ที่สร้างขึ้นบนพื้นฐานของ Widget Tree และจัดการการแทรก widget ในแอปพลิเคชัน อินสแตนซ์องค์ประกอบแต่ละอันสอดคล้องกับหนึ่ง widget ในทรีและเก็บข้อมูลอ้างอิงไปยังมัน ความแตกต่างหลักระหว่างองค์ประกอบและ widget คือ องค์ประกอบรักษาตำแหน่งในทรีระหว่างการสร้างใหม่ ในขณะที่ widget อาจถูกสร้างใหม่ทุกครั้งที่มีการเรียก build

ทำไมต้องใช้ Element Tree

หากไม่มี Element Tree Flutter จะไม่สามารถอัปเดตอินเทอร์เฟซได้อย่างมีประสิทธิภาพ หากทุกการ rebuild สร้าง RenderObject Tree ใหม่ ประสิทธิภาพจะต่ำอย่างไม่อาจยอมรับได้ Element Tree ทำหน้าที่เป็นตัวทำให้เสถียร: มันเก็บข้อมูลอ้างอิงไปยัง RenderObject และ State ระหว่างการอัปเดต ทำให้ Flutter สามารถใช้การเปลี่ยนแปลงเพียงเล็กน้อยกับทรีการเรนเดอร์

ประเภทขององค์ประกอบ

Flutter ใช้องค์ประกอบสามประเภทหลัก: StatelessElement สำหรับ StatelessWidget, StatefulElement สำหรับ StatefulWidget และ LeafRenderObjectElement, SingleChildRenderObjectElement, MultiChildRenderObjectElement สำหรับ RenderObjectWidget แต่ละประเภทมีความเชี่ยวชาญสำหรับคลาส widget ของตนและกำหนดว่าองค์ประกอบโต้ตอบกับ RenderObject อย่างไร

ความสัมพันธ์ระหว่าง Widget, Element และ RenderObject ในสถาปัตยกรรมสามชั้น

สถาปัตยกรรมสามชั้น ของ Flutter ประกอบด้วย Widget Tree (การกำหนดค่า), Element Tree (การจัดการ) และ RenderObject Tree (การเรนเดอร์) Element Tree คือจุดเชื่อมต่อ: มันอ่านการกำหนดค่าจาก Widget และส่งคำสั่งไปยัง RenderObject หากไม่มี Element Tree เฟรมเวิร์กจะไม่สามารถซิงโครไนซ์คำอธิบายแบบประกาศกับการเรนเดอร์จริงได้อย่างมีประสิทธิภาพ

องค์ประกอบเชื่อมต่อ widget และ RenderObject อย่างไร

เมื่อองค์ประกอบถูกเมาท์ในทรี มันจะตรวจสอบประเภทของ widget ถ้า widget เป็น RenderObjectWidget องค์ประกอบจะสร้าง RenderObject ที่สอดคล้องและเพิ่มลงใน RenderObject Tree ถ้า widget เป็น LeafRenderObjectWidget องค์ประกอบจะสร้าง RenderObject ใบ สำหรับ StatelessWidget และ StatefulWidget องค์ประกอบเพียงแค่จัดการการเมาท์ขององค์ประกอบลูก

dart
abstract class Element {
  Widget widget;
  Element? parent;
  List<Element>? children;

  void mount(Element? parent, dynamic newSlot);
  void update(Widget newWidget);
  void unmount();
}

โค้ดที่เรียบง่ายนี้แสดงโครงสร้างพื้นฐานของ Element แต่ละองค์ประกอบเก็บข้อมูลอ้างอิงไปยัง widget ปัจจุบัน องค์ประกอบหลัก และองค์ประกอบลูก เมธอด mount, update และ unmount จัดการวงจรชีวิตขององค์ประกอบและ RenderObject ที่เกี่ยวข้อง

วงจรชีวิตขององค์ประกอบ: จากการสร้างจนถึงการลบ

แต่ละองค์ประกอบ ใน Flutter ผ่านลำดับของขั้นตอนวงจรชีวิต: การสร้าง การเมาท์ การอัปเดต และการ unmount การทำความเข้าใจขั้นตอนเหล่านี้จำเป็นสำหรับการดีบักพฤติกรรมที่ไม่คาดคิด โดยเฉพาะเมื่อทำงานกับแอนิเมชัน การดำเนินการแบบอะซิงโครนัส และการจัดการสถานะ

ขั้นตอนที่ 1: การสร้างองค์ประกอบ

องค์ประกอบถูกสร้างขึ้นโดยเรียกเมธอด createElement ของ widget สำหรับ StatelessWidget จะสร้าง StatelessElement; สำหรับ StatefulWidget จะสร้าง StatefulElement (ซึ่งสร้างออบเจ็กต์ State ด้วย); สำหรับ RenderObjectWidget จะสร้าง RenderObjectElement ที่สอดคล้อง การสร้างองค์ประกอบเกิดขึ้นเมื่อ widget ปรากฏครั้งแรกใน Widget Tree

ขั้นตอนที่ 2: การเมาท์ (mount)

ระหว่างการเมาท์ องค์ประกอบจะถูกเพิ่มลงใน Element Tree และรับองค์ประกอบหลัก สำหรับ RenderObjectElement การเมาท์ยังสร้าง RenderObject และแทรกลงใน RenderObject Tree ด้วย ถ้า widget เป็น StatefulElement ในขั้นตอนนี้เมธอด initState ของออบเจ็กต์ State จะถูกเรียก

ขั้นตอนที่ 3: การอัปเดต (update)

เมื่อ widget ถูกสร้างใหม่ด้วยการกำหนดค่าใหม่ องค์ประกอบจะได้รับ widget ใหม่ผ่านเมธอด update องค์ประกอบเปรียบเทียบประเภทของ widget เก่าและใหม่: ถ้าประเภทตรงกัน องค์ประกอบจะอัปเดตการกำหนดค่า; ถ้าไม่ตรงกัน องค์ประกอบจะถูก unmount และสร้างใหม่ สิ่งนี้เรียกว่า "การเปลี่ยน widget" และเป็นสาเหตุของการสูญเสียสถานะเมื่อเปลี่ยนประเภท

ขั้นตอนที่ 4: การ unmount (unmount)

เมื่อ widget ถูกลบออกจาก Widget Tree เมธอด unmount ขององค์ประกอบจะถูกเรียก องค์ประกอบถูกลบออกจาก Element Tree RenderObject ถูกลบออกจาก RenderObject Tree และสำหรับ StatefulWidget เมธอด dispose ของออบเจ็กต์ State จะถูกเรียก หลังจาก unmount องค์ประกอบสามารถนำกลับมาใช้ใหม่ได้ถ้า widget ปรากฏอีกครั้งในตำแหน่งเดียวกัน

บทบาทของคีย์ใน Element Tree

คีย์ (Key) เป็นกลไกการระบุองค์ประกอบที่ช่วยให้ Flutter จับคู่ widget จาก Widget Tree เก่าและใหม่ไม่ใช่ตามตำแหน่ง แต่ตามตัวระบุที่ไม่ซ้ำกัน คีย์มีความสำคัญอย่างยิ่งเมื่อทำงานกับรายการแบบไดนามิกที่ลำดับขององค์ประกอบสามารถเปลี่ยนแปลงได้: การเพิ่ม การลบ หรือการจัดเรียงองค์ประกอบใหม่

คีย์ส่งผลต่อ Element Tree อย่างไร

หากไม่มีคีย์ Flutter จะจับคู่องค์ประกอบตาม ตำแหน่ง ในทรี: องค์ประกอบที่ตำแหน่ง 0 จากทรีเก่าจะถูกแทนที่ด้วย widget ที่ตำแหน่ง 0 จากทรีใหม่ ถ้าลำดับเปลี่ยนแปลงไป องค์ประกอบจะปะปนกันและสถานะอาจสูญหายหรือถูกผูกกับข้อมูลที่ไม่ถูกต้อง คีย์บังคับให้ Flutter ค้นหาองค์ประกอบตามตัวระบุแทนที่จะเป็นตามตำแหน่ง

ValueKey, ObjectKey และ UniqueKey

ValueKey ใช้ค่าอย่างง่าย (สตริง ตัวเลข) เพื่อระบุองค์ประกอบ ObjectKey ใช้การอ้างอิงออบเจ็กต์ — เหมาะสมเมื่อองค์ประกอบไม่มีตัวระบุสตริงที่เสถียร UniqueKey สร้างตัวระบุที่ไม่ซ้ำกันทุกครั้งที่สร้าง — ใช้เมื่อแต่ละอินสแตนซ์ของ widget ต้องไม่ซ้ำกัน

dart
Column(
  children: items.map((item) => TodoItem(
    key: ValueKey(item.id),
    title: item.title,
    isDone: item.isDone,
  )).toList(),
)

ในตัวอย่างนี้ ValueKey กับ item.id รับประกันว่าแต่ละ TodoItem จะคงสถานะของมันไว้ (เช่น การโฟกัสของช่องป้อนข้อมูล) เมื่อลำดับขององค์ประกอบในรายการเปลี่ยนไป หากไม่มีคีย์ องค์ประกอบที่ตำแหน่งแรกจะได้รับสถานะขององค์ประกอบก่อนหน้าที่ตำแหน่งเดียวกัน

Element Tree จัดการสถานะอย่างไร

สถานะ (State) ใน Flutter ไม่ได้เก็บไว้ใน widget แต่อยู่ในองค์ประกอบ เมื่อ StatefulWidget ถูกสร้างใหม่และสร้างอินสแตนซ์ widget ใหม่ StatefulElement ที่สอดคล้องจะเก็บข้อมูลอ้างอิงไปยังออบเจ็กต์ State เก่า widget ใหม่เชื่อมต่อกับ State ที่มีอยู่ ทำให้ข้อมูลถูกเก็บรักษาไว้ระหว่างการสร้างใหม่

ทำไมสถานะถึงไม่สูญเสียเมื่อสร้างใหม่

ระหว่างการสร้าง widget ใหม่ Flutter จะสร้างอินสแตนซ์ใหม่ของ StatefulWidget แต่ StatefulElement ที่สอดคล้องยังคงอยู่ใน Element Tree องค์ประกอบเรียกเมธอด update บน State โดยส่ง widget ใหม่ ดังนั้น ออบเจ็กต์ State และข้อมูลของมันจึงถูกเก็บรักษาไว้ การสูญเสียสถานะเกิดขึ้นเมื่อประเภทของ widget เปลี่ยนไป คีย์เปลี่ยนไป หรือองค์ประกอบถูกลบออกจากทรี

InheritedWidget และ Element Tree

InheritedElement เป็นองค์ประกอบพิเศษที่ช่วยให้องค์ประกอบลูกได้รับข้อมูลจาก InheritedWidget หลักโดยไม่ต้องส่งผ่านคอนสตรัคเตอร์อย่างชัดเจน เมื่อ InheritedWidget เปลี่ยนแปลง InheritedElement จะแจ้งให้องค์ประกอบที่ขึ้นต่อกันทั้งหมดทราบ ซึ่งจะถูกสร้างใหม่ กลไกนี้เป็นพื้นฐานของ Theme, MediaQuery และ Provider

  • การขึ้นต่อกัน — องค์ประกอบลงทะเบียนเป็นผู้ขึ้นต่อกันของ InheritedElement เมื่อเรียก dependOnInheritedWidgetOfExactType
  • การแจ้งเตือน — เมื่อ InheritedWidget เปลี่ยนแปลง เฟรมเวิร์กจะทำเครื่องหมายองค์ประกอบที่ขึ้นต่อกันทั้งหมดว่าต้องการการสร้างใหม่
  • การสร้างใหม่ — องค์ประกอบที่ขึ้นต่อกันจะถูกสร้างใหม่ในเฟรมถัดไป โดยอัปเดต UI ตามข้อมูลใหม่

ผลกระทบของ Element Tree ต่อประสิทธิภาพ

Element Tree ใช้หน่วยความจำและส่งผลต่อความเร็วในการเรนเดอร์ครั้งแรก แต่ละองค์ประกอบใช้หน่วยความจำจำนวนหนึ่ง: การอ้างอิงไปยัง widget การอ้างอิงไปยังหลัก รายการขององค์ประกอบลูก ช่อง และฟิลด์เพิ่มเติมสำหรับ RenderObjectElement การปรับ Element Tree ให้เหมาะสมจะลดเวลาเริ่มต้นและลดการใช้หน่วยความจำ

การนำองค์ประกอบกลับมาใช้ใหม่

Flutter พยายาม นำองค์ประกอบกลับมาใช้ใหม่ ระหว่างการสร้างใหม่ ถ้า widget ในการกำหนดค่าใหม่มีประเภทและคีย์เดียวกัน องค์ประกอบจะไม่ถูกสร้างใหม่ — มันจะถูกอัปเดต สิ่งนี้เร็วกว่าการสร้างองค์ประกอบใหม่ด้วยการเมาท์ตามมาอย่างมาก อย่างไรก็ตาม เมื่อประเภทหรือคีย์เปลี่ยนแปลง องค์ประกอบเก่าจะถูก unmount และสร้างองค์ประกอบใหม่ตั้งแต่ต้น

RepaintBoundary และ Element Tree

RepaintBoundary สร้าง RenderRepaintBoundary แยกต่างหากใน RenderObject Tree ที่แยกส่วนหนึ่งของทรีออกจากกัน ที่ระดับ Element Tree RepaintBoundary ไม่ได้สร้างองค์ประกอบพิเศษ — มันใช้ SingleChildRenderObjectElement ความแตกต่างปรากฏที่ระดับ RenderObject: เมื่อเนื้อหาของ RepaintBoundary เปลี่ยนแปลง เฉพาะพื้นที่ที่ถูกแยกเท่านั้นที่ถูกวาดใหม่

การดำเนินการไม่มี RepaintBoundaryมี RepaintBoundary
การวาดใหม่ทั้งหน้าจอเฉพาะพื้นที่ที่ถูกแยก
เวลา~16 ms ที่ 60 FPS~2-5 ms
หน่วยความจำน้อยที่สุด+ ไม่กี่กิโลไบต์ต่อชั้น

ดังที่ตารางแสดง RepaintBoundary ลดเวลาในการวาดใหม่ลงอย่างมากโดยการแยกพื้นที่ที่เปลี่ยนแปลง ที่ระดับ Element Tree ไม่จำเป็นต้องกำหนดค่าเพิ่มเติม — เพียงห่อ widget ที่เปลี่ยนแปลงด้วย RepaintBoundary

คำถามที่พบบ่อย

ความแตกต่างระหว่าง Widget Tree และ Element Tree คืออะไร?

Widget Tree คือการกำหนดค่าที่ถูกสร้างใหม่ทุกครั้งที่มีการสร้างใหม่ Element Tree คือโครงสร้างถาวรที่คงอยู่ระหว่างการอัปเดตและจัดการสถานะ RenderObject และวงจรชีวิตของ widget

ทำไม Element Tree ถึงสำคัญต่อประสิทธิภาพ?

หากไม่มี Element Tree Flutter จะต้องสร้าง RenderObject Tree ใหม่ทุกครั้งที่สถานะเปลี่ยนแปลง ซึ่งจะทำให้เกิด ความล่าช้าอย่างมาก Element Tree จะเก็บรักษา RenderObject และ State ไว้ ทำให้สามารถใช้การเปลี่ยนแปลงเพียงเล็กน้อยเท่านั้น

เมื่อใดที่องค์ประกอบถูกลบออกจาก Element Tree?

องค์ประกอบถูกลบเมื่อ widget ที่สอดคล้องหายไปจาก Widget Tree หรือเมื่อ ประเภทของ widget เปลี่ยนไป (เช่น Column ถูกแทนที่ด้วย Row) หรือคีย์เปลี่ยนไป เมื่อ unmount จะเรียก dispose บน State

คีย์ส่งผลต่อ Element Tree อย่างไร?

คีย์ เปลี่ยนอัลกอริทึมการจับคู่: แทนที่จะค้นหาองค์ประกอบตามตำแหน่ง Flutter จะค้นหาองค์ประกอบตามค่าคีย์ ซึ่งช่วยให้รักษาสถานะไว้ได้เมื่อลำดับหรือจำนวนของ widget เปลี่ยนแปลง

สามารถเข้าถึง Element Tree โดยตรงได้หรือไม่?

ได้ ผ่าน BuildContext ซึ่งเป็นนามธรรมขององค์ประกอบ เมธอด findAncestorWidgetOfExactType และ dependOnInheritedWidgetOfExactType ทำงานกับ Element Tree โดยเลื่อนขึ้นไปตามทรีขององค์ประกอบ

สรุป

  • Element Tree — เลเยอร์กลางถาวรระหว่าง Widget และ RenderObject Tree ที่เก็บรักษาสถานะระหว่างการสร้างใหม่
  • แต่ละ widget สร้างองค์ประกอบ: StatelessElement, StatefulElement หรือ RenderObjectElement ขึ้นอยู่กับประเภทของ widget
  • วงจรชีวิต ขององค์ประกอบรวมถึงการสร้าง การเมาท์ การอัปเดต และการ unmount — การทำความเข้าใจขั้นตอนเหล่านี้จำเป็นสำหรับการดีบัก
  • คีย์ (Key) ทำงานที่ระดับ Element Tree เพื่อให้แน่ใจว่ามีการจับคู่ widget ที่ถูกต้องระหว่างการเปลี่ยนแปลงแบบไดนามิก
  • StatefulElement เก็บออบเจ็กต์ State ที่คงอยู่ระหว่างการสร้าง widget ใหม่ถ้าประเภทและคีย์ไม่เปลี่ยนแปลง
  • InheritedElement แจ้งองค์ประกอบที่ขึ้นต่อกันเกี่ยวกับการเปลี่ยนแปลง ทำให้สามารถแพร่กระจายข้อมูลแบบรีแอกทีฟลงไปในทรี
  • สถาปัตยกรรมสามชั้น Widget → Element → RenderObject ช่วยให้ Flutter อัปเดต UI ได้อย่างมีประสิทธิภาพ ลดการดำเนินการเรนเดอร์ที่แพง

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม