เป็นบทความสั้นๆเพื่ออัพเดทรูปแบบการเขียนโค้ดของคำสั่ง findViewById
แบบใหม่ให้กับผู้ที่หลงเข้ามาอ่านซักหน่อย ถึงแม้ว่าผู้ที่หลงเข้ามาอ่านหลายๆคนจะรู้เรื่องนี้กันแล้ว แต่ก็น่าจะมีบางคนที่ยังไม่รู้หลงเหลืออยู่บ้าง
แต่ถ้าเปลี่ยนไปใช้ ViewBinding จะดีกว่านะ
ใครไม่รู้จักคำสั่ง findViewById บ้าง?
ตั้งแต่สมัยที่แอนดรอยด์ถูกสร้างขึ้นมาจวบจนมาถึงทุกวันนี้ เรียกได้ว่าไม่มีนักพัฒนาคนไหนไม่เคยเห็นคำสั่ง findViewById
มาก่อน เพราะว่ามันคือคำสั่งแรกๆที่ทุกคนได้รู้จักกัน ซึ่งคำสั่งจะมีลักษณะแบบนี้
Button btnConfirm = (Button) findViewById(R.id.btnConfirm);
TextView tvRegistrationInfo = (TextView) findViewById(R.id.tvRegistrationInfo);
และนักพัฒนาทุกคนก็จะจำกันได้อย่างแม่นยำว่า
- ถ้าเป็น Button ก็ต้อง Cast ให้เป็น Button ก่อนทุกครั้ง
- ถ้าเป็น RecyclerView ก็ต้อง Cast ให้เป็น RecyclerView ก่อนทุกครั้ง
- ถ้าเป็น LinearLayout ก็ต้อง Cast ให้เป็น LinearLayout ก่อนทุกครั้ง
- ฯลฯ
เพราะว่า findViewById
เป็นคำสั่งที่จะส่งค่ากลับมาเป็น View ทุกครั้ง
View findViewById (int id)
ก็เลยต้องแปลงคลาสให้เป็นคลาสที่ต้องการใช้งาน โดยจะต้องเป็นคลาสที่สืบทอดมาจาก View นั่นเอง
ซึ่งการที่ต้องมานั่งแปลงคลาสทุกครั้งเวลาจะใช้งานนั้นเป็นอะไรที่ค่อนข้างน่าเบื่อเหมือนกันนะ จนนักพัฒนาหลายๆคนได้หาตัวช่วยอื่นๆเข้ามาแทนที่มากมาย ไม่ว่าจะใช้ ButterKnife หรือว่า DataBinding เพื่อเลี่ยงคำสั่งจำเจอย่าง findViewById
แต่ทว่ามันก็ยังเป็นคำสั่งยอดนิยมที่ส่วนใหญ่ใช้งานกันอยู่ดีน่ะแหละ
ถึงเวลาของ findViewByid แบบใหม่แล้ว!
ในงาน Google I/O 2017 ที่ผ่านมาได้มีการประกาศอย่างหล่อๆว่า “ต่อไปนี้ไม่ต้องแปลงคลาสเวลาเรียกใช้งาน findViewById
อีกต่อไปแล้ว!!!”
นั่นก็เพราะว่าคำสั่ง findViewById จะถูกเปลี่ยนใหม่ให้กลายเป็นแบบนี้แทน
T findViewById (int id)
ซึ่ง T
ที่ว่านี้คือคลาสใดๆขึ้นอยู่กับว่า ID ที่กำหนดนั้นเป็น View แบบไหน ถ้าเป็นของ Button มันก็จะได้ออกมาเป็นคลาส Button โดยอัตโนมัติ และเวลาเรียกใช้คำสั่ง findViewById
ก็ไม่ต้องเสียเวลามานั่งแปลงคลาสอีกต่อไป
Button btnConfirm = findViewById(R.id.btnConfirm);
TextView tvRegistrationInfo = findViewById(R.id.tvRegistrationInfo);
โดยจะสังเกตได้จาก Android Studio ที่คอยแจ้งเตือนในโค้ดว่า “ให้ลบออกได้แล้ววววว”
อ้าว ทำไมของบางคนยังต้องแปลงคลาสอยู่ล่ะ?
การใช้งาน findViewById
แบบใหม่นั้นจะมีอยู่ 2 เงื่อนไขด้วยกัน ซึ่งรองรับการใช้งานกับแอนดรอยด์เวอร์ชันเก่าๆด้วยนะ
ถ้าอยากใช้งานบน Android Framework : โปรเจคต้องกำหนดเป็น API 26 ขึ้นไป
ในกรณีที่อยากจะให้คลาส Activity หรือ View ของ Android Framework เดิมนั้นรองรับ findViewById
แบบใหม่ จะต้องกำหนดโปรเจคให้ใช้ API 26 ขึ้นไปครับ ทางที่ดีก็ให้กำหนดเหมือนๆกันทั้ง compileSdkVersion
, buildToolsVersion
และ targetSdkVersion
ไปเลย จะได้ไม่ต้องวุ่นวายอะไรมากนัก
android {
compileSdkVersion 26
buildToolsVersion "26.0.1"
defaultConfig {
targetSdkVersion 26
/* ... */
}
/* ... */
}
ส่วน minSdkVersion
จะกำหนดเป็นเวอร์ชันอะไรก็ได้
ถ้าอยากใช้งานบน Android Support Library : Library ต้องกำหนดเป็นเวอร์ชัน 26 ขึ้นไป
แต่สมัยนี้คงใช้เป็น AndroidX กันหมดแล้วแหละ เพราะงั้นข้ามไปได้เลยนะ
เจ้าของบล็อกก็เป็นคนหนึ่งที่เลิกใช้คลาส Activity แบบเดิมๆแล้ว เพราะเปลี่ยนไปใช้พวก AppCompatActivity แทนเพื่อให้ใช้งาน Android Support Library ตัวอื่นๆได้สะดวก
ดังนั้นถ้าอยากใช้ findViewById
แบบใหม่ ก็จะต้องกำหนดให้ Android Support Library ทุกตัวในโปรเจคใช้เป็นเวอร์ชัน 26 ขึ้นไปซะ
dependencies {
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support:design:26.1.0'
implementation 'com.android.support:customtabs:26.1.0'
/* ... */
}
สรุป
คำสั่ง findViewById
แบบใหม่นี้จะช่วยให้ลดคำสั่งน่าเบื่อหน่ายให้น้อยลง ไม่ต้องมานั่งแปลงคลาสทุกครั้งอีกต่อไป ซึ่งถือว่าเป็นเรื่องที่ดีไม่น้อย แต่ทว่าปัญหาในตอนนี้ก็คงจะเป็นเนื้อหาต่างๆที่มีอยู่ในทั้งหนังสือ, วีดีโอ หรืออินเตอร์เน็ตนั้นยังคงเป็นแบบเดิมอยู่ จึงทำให้หลายๆคนก็ยังใส่คำสั่งแปลงคลาสอยู่ ทั้งๆที่สามารถลบทิ้งได้ จึงหวังว่าบทความนี้น่าจะช่วยให้ผู้ที่หลงเข้ามาอ่านสามารถปรับรูปแบบโค้ดให้เหมาะสมกับยุคสมัยได้ ไม่ใช่เดิมเคยทำยังไงก็ทำแบบนั้นไปเรื่อยๆ
ในแง่ของการ Migrate ถ้ามีโปรเจคที่กำลังทำอยู่หรือโปรเจคเก่าๆ ก็สามารถอัพเดท SDK ในโปรเจคและ Library ของ Android Support Library ให้เป็นเวอร์ชัน 26 แล้วไล่ลบคำสั่งแปลงคลาสออกได้เลย แต่ถ้าโปรเจคเก่ามากๆแนะนำให้เช็คก่อนว่ามีการทำงานอย่างอื่นที่ส่งผลกระทบด้วยหรือป่าว เช่น Migrate มาจาก API 21 เป็น API 26 ก็ควรจะเช็คเรื่อง Runtime Permission ของ API 23 ด้วย
แต่ถ้าไปใช้ DataBinding หรือ ViewBinding ไปเลย น่าจะสะดวกกว่านะ ฮ่าๆ