PETEPITTAWAT.DEV

Flutter: BuildContext Deep Dive รู้ให้ลึกกับ BuildContext

Cover Image for Flutter: BuildContext Deep Dive รู้ให้ลึกกับ BuildContext
Pittawat Taveekitworachai
Pittawat Taveekitworachai

BuildContext สิ่งที่ปรากฎตัวแทบทุกที่ในโค้ดของเรา และเป็นสิ่งที่นักพัฒนา Flutter ต้องใช้ชีวิตอยู่กับมันให้ได้ หลายครั้งบางคนก็อาจไม่เข้าใจว่าเราจะใช้ Context ไปทำไม แต่นี่ไม่ใช่คอนเซปใหม่เลย ในหลายภาษา Context ก็ไปปรากฎตัวเช่นเดียวกัน

Context ถูกใช้เพื่อบ่งบอกถึงตำแหน่งของสิ่งต่าง ๆ ในสิ่งต่าง ๆ เห็นแบบนี้แล้วอาจจะงง หากกล่าวให้เจาะจงกับ Flutter มากขึ้น BuildContext เป็นสิ่งที่ใช้สำหรับบ่งบอกตำแหน่งของ Widget บน Widget Tree ดังนั้น Context ที่เราเรียกใช้กันบ่อย ๆ จึงไม่ได้หมายถึงตัวเดียวกันเสมอไป

โดยปกติแล้ว BuildContext จะถูกอ้างอิงถึง Widget ตัวนั้น ๆ ที่เรากำลังอยู่ ซึ่งภายใน Context จะบรรจุไปด้วยเมธอดต่าง ๆ มากมายที่เราใช้ได้จากการที่เราสั่ง build Widget นั้น ๆ (และหากเป็น StatefulWidget เราจะสามารถใช้เมธอดที่มาจาก State ได้ด้วย)

โดยทั่วไปแล้วเรามักเห็นการใช้ Context ใน 2 รูปแบบหลัก ๆ คือ

  1. การส่งเป็นค่าหนึ่งให้กับข้อมูลนำเข้าของเมธอด

  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 นั้นก็ไม่ใช่สิ่งที่ได้รับการแนะนำสักเท่าไรนัก


📚 Hope you enjoy reading! 📚