เป็นบทความสั้นๆเพื่ออัพเดทรูปแบบการเขียนโค้ดของคำสั่ง findViewById แบบใหม่ให้กับผู้ที่หลงเข้ามาอ่านซักหน่อย ถึงแม้ว่าผู้ที่หลงเข้ามาอ่านหลายๆคนจะรู้เรื่องนี้กันแล้ว แต่ก็น่าจะมีบางคนที่ยังไม่รู้หลงเหลืออยู่บ้าง
ใครไม่รู้จักคำสั่ง 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 ขึ้นไป
เจ้าของบล็อกก็เป็นคนหนึ่งที่เลิกใช้คลาส 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 ด้วย
แต่ถ้าไปใช้ ButterKnife, DataBinding หรือเขียนด้วย Kotlin ไปเลย น่าจะสะดวกกว่านะ ฮ่าๆ