[Android] ViewStub : Zero-sized view “เมื่อไรเขามา ฉันจะไป”

Teeranai.P
King Power Click
Published in
2 min readFeb 6, 2020

ตอนที่เริ่มเขียน Android หลายๆท่านคงเคยผ่านตามาบ้างกับ Android Component ที่ชื่อว่า ViewStub ซึ่งผมก็เป็นหนึ่งคนที่ได้แค่ผ่านๆตาแต่ไม่เคยลองใช้งาน วันนี้ก็เลยหยิบเอามาเขียนซักเล็กน้อยครับ

ViewStub คืออะไร ?

ViewStub คือ View ชนิดหนึ่ง มีการใช้งาน Memory น้อยมากกกกกก เนื่องจากไม่มีการเขียนอะไรลงบนจอเลย (Zero-sized View) ด้วยเหตุนี้ ViewStub จึงไม่ปรากฏบนจอ

โดยที่ไม้เด็ดของ ViewStub คือ สามารถ Inflate View อื่นๆ เข้ามาแทนที่ตัวมันเอง ในขณะ Runtime ได้ เพียงแค่เรียกใช้คำสั่ง ViewStub.inflate() หรือ ViewStub.setVisibility() ซึ่งเป็นที่มาของหัวข้อเรื่องที่ว่า “เมื่อไรเขามา ฉันจะไป” นั่นเอง

ใช้งานเมื่อไร ?

ViewStub เหมาะสำหรับการใช้งานกับ View ที่ไม่ได้แสดงผลทุกครั้งในหน้าเดิมๆ หรือ View ที่นานๆทีจะแสดงผลสักครั้งนึง เช่น แถบคาดว่า User ถูกแบน, Progress bar แสดง % ในการ Download ข้อมูล เป็นต้น

เนื่องจากว่า ViewStub ไม่มีการแสดงผลลงบนจอและมี View Hierarchy เพียงชั้นเดียว จึงทำให้ใช้งาน Memory น้อยกว่ามาก เมื่อเทียบกับการที่ใส่ View ลงไปตรงๆใน XML แล้วสั่ง visibility="gone" เพราะถึงแม้ว่าจะซ่อนไปแล้ว View นั้นๆก็ยังจะโดน Inflate อยู่ดี ซึ่งก็หมายถึง Memory ที่ต้องเสียไปโดยเปล่าประโยชน์ นั่นเอง :(

การใช้งาน

หน้าตาของ ViewStub ในไฟล์ .xml

android:inflatedId คือ การกำหนด Id ให้กับ View ที่ Inflate มาแทน ViewStub
android:layout คือ ไฟล์ layout .xml ที่ต้องการให้มาแทน ViewStub

และเมื่อต้องการให้ View อื่นมาแทนที่ ViewStub ก็เพียงเรียกคำสั่งดังตัวอย่าง

การใช้งาน ViewStub ก็มีเพียงเท่านี้ แต่บางท่านอาจจะยังงงๆอยู่ เพื่อความเข้าใจมากขึ้นเราลองมาทำ Work Shop กันดีกว่าครับ :)

ลองทำ Work Shop ง่ายๆกันดีกว่า

โจทย์คือ
— หาก User อยู่ในสถานะปกติ ก็ให้แสดง Avatar ของ User (A)
— แต่หาก User ถูกแบน ให้แสดง Overlay สีดำทับพร้อมกับแสดงข้อความ (B)

1. สร้าง Layout ของ User Avatar

ขอตั้งชื่อว่า activity_user.xml ก็จะได้ผลลัพธ์จะได้ดังรูป (A) ด้านบน

2. ลองเพิ่ม Layout ของ Overlay สีดำและข้อความลงไปใน Layout เดิม

ผลลัพธ์จะได้ดังรูป (B) ด้านบน

จริงๆ แล้วทำเพียงเท่านี้ก็เพียงพอต่อความต้องการของโจทย์แล้ว แต่เดี๋ยวก่อน Layout Overlay สีดำไม่ได้แสดงทุกครั้งใช่ไหมครับ :) แล้วเราจะทำยังไงหละ??

ถูกต้องนะคร้าบบบ ViewStub ช่วยท่านได้ ลองมาดูกันดีกว่า

3. ย้าย Layout ของ Overlay สีดำและข้อความ ไปไว้อีกไฟล์นึง

ขอตั้งชื่อว่า banned_user.xml

Warning!! — View ที่จะ Inflate เข้ามาแทน ViewStub ไม่รองรับการใช้งาน tag <merge /> นะครับ

4. กลับไปที่ activity_user.xml เพื่อเพิ่ม ViewStub

การกำหนด View ที่จะมาแทน ViewStub ทำได้ด้วยการกำหนด property android:layout="@layout/banned_user" ให้ ViewStub

5. เมื่อ User ถูกแบน ให้เรียกใช้คำสั่ง ViewStub.inflate()

เพียงเท่านี้ก็จะได้ผลลัพธ์ตามที่โจทย์ต้องการ พร้อมทั้งยังได้ Application ที่ประสิทธิภาพอีกด้วยนะครับ

แอบดูเบื้องหลังกันหน่อย

ลองมาดู View Hierarchy ระหว่างตอนที่ยังเป็น ViewStub (1) และหลังจาก Inflate View (2) อื่นเข้ามาแทนกันหน่อย

จะเห็นได้ว่า android:inflatedId ที่กำหนดไว้ให้กับ ViewStub ถูกกำหนดเป็น ID ให้กับ View ที่ถูก Inflate เข้ามาแทนนั่นเอง ส่วนเรื่อง View Hierarchy จากภาพด้านบนคงจะพอบอกได้แล้วว่า ViewStub ดียังไง

สำหรับเรื่องของ ViewStub คงจบลงเท่านี้ สุดท้ายหากมีข้อสงสัยหรือแนะนำก็ฝากไว้ใน Comment ได้เลยนะครับ ขอบคุณครับ

ปล. ดูโค้ดทั้งหมดได้ที่ github.com

--

--