Flutter: BuildContext Deep Dive รู้ให้ลึกกับ BuildContext
Published on
Authored by Pete. Pittawat Taveekitworachai.
BuildContext
สิ่งที่ปรากฎตัวแทบทุกที่ในโค้ดของเรา และเป็นสิ่งที่นักพัฒนา Flutter ต้องใช้ชีวิตอยู่กับมันให้ได้ หลายครั้งบางคนก็อาจไม่เข้าใจว่าเราจะใช้ Context ไปทำไม แต่นี่ไม่ใช่คอนเซปใหม่เลย ในหลายภาษา Context ก็ไปปรากฎตัวเช่นเดียวกัน
Context ถูกใช้เพื่อบ่งบอกถึงตำแหน่งของสิ่งต่าง ๆ ในสิ่งต่าง ๆ เห็นแบบนี้แล้วอาจจะงง หากกล่าวให้เจาะจงกับ Flutter มากขึ้น BuildContext
เป็นสิ่งที่ใช้สำหรับบ่งบอกตำแหน่งของ Widget บน Widget Tree ดังนั้น Context ที่เราเรียกใช้กันบ่อย ๆ จึงไม่ได้หมายถึงตัวเดียวกันเสมอไป
โดยปกติแล้ว BuildContext
จะถูกอ้างอิงถึง Widget ตัวนั้น ๆ ที่เรากำลังอยู่ ซึ่งภายใน Context จะบรรจุไปด้วยเมธอดต่าง ๆ มากมายที่เราใช้ได้จากการที่เราสั่ง build
Widget นั้น ๆ (และหากเป็น StatefulWidget
เราจะสามารถใช้เมธอดที่มาจาก State
ได้ด้วย)
โดยทั่วไปแล้วเรามักเห็นการใช้ Context ใน 2 รูปแบบหลัก ๆ คือ
-
การส่งเป็นค่าหนึ่งให้กับข้อมูลนำเข้าของเมธอด
-
การใช้งานผ่าน of
สำหรับตัวอย่างในการใช้แบบแรกนั้น เรามักรู้จักกันดีในการใช้งานกับพวก showDialog
เป็นต้น ซึ่งต้องใช้เพื่อให้สามารถจัดการในเรื่องการโชว์ Dialog ซ้อนไปบนหน้าจอ และกลับออกมาได้อย่างถูกต้อง
ส่วนแบบที่สองนั้นก็มักจะพบได้กับการใช้ผ่าน Navigator.of(context)
และ Theme.of(context)
สำหรับ Navigator.of(context)
จำเป็นต้องมี Context เพื่อให้สามารถจัดการ Stack ที่ใช้บันทึกหน้าจอต่าง ๆ ได้อย่างถูกต้องว่าหน้าใดมาก่อนหลัง เพื่อไป/กลับได้ถูก ส่วน Theme.of(context)
นั้นเปรียบได้กับการดึงข้อมูล ThemeData
ที่ถูกส่งมาให้โดย MaterialApp
หรือ CupertinoApp
แล้วนำมาใช้ (จริง ๆ แล้ว อาจเป็น Widget ตัวอื่น ๆ ได้หาก Widget นั้นมีการใช้งาน Widget Theme
ครอบอยู่)
นี่ทำให้เราเห็นได้ว่า Context นอกจากจะถูกใช้เพื่อบอกตำแหน่งว่าเป็น Widget ตัวไหน และอยู่ส่วนไหนของ Widget Tree แล้ว ยังถูกใช้สำหรับเก็บข้อมูลที่มีลักษณะ Global ในบางครั้งอีกด้วย
อีกหนึ่งอย่างที่ค่อนข้าง Tricky สำหรับ BuildContext
ก็คือหากอ้างอิงตามคำอธิบายข้างต้นแล้วนั่นหมายความว่า BuildContext
ในเมธอด build
ของ Widget จะไม่ใช่ตัวเดียวกับ BuildContext
ของ Widget ที่ถูกคืนค่าออกมาด้วย build
(ตอนที่อยู่ในเมธอด build
จะใช้ BuildContext
ที่ได้รับมาจาก Widget ที่เป็นเจ้าของ build
ส่วนตอนคืนค่าต้องมีการสร้าง BuildContext
ใหม่เพื่อบอกถึงตำแหน่งบน Widget Tree ของ Child)
นอกจากนี้ BuildContext
ของ Widget ไม่จำเป็นต้องอยู่ที่เดิมเสมอไป เนื่องจาก Widget นั้น ๆ อาจเปลี่ยนตำแหน่งไปมาบน Widget Tree ได้ ค่าที่เราคาดหวังจึงอาจไม่มีเสมอไป
จริง ๆ แล้ว BuildContext
เป็น Object ประเภท Element
อย่างไรก็ตามการจะดำเนินการต่าง ๆ เกี่ยวกับ Element
ผ่าน BuildContext
นั้นก็ไม่ใช่สิ่งที่ได้รับการแนะนำสักเท่าไรนัก