17 September 2017

[Android Dev Tips] ยุคนี้ทั้งที เปลี่ยน findViewById เป็นแบบใหม่กันเถอะ



        เป็นบทความสั้นๆเพื่ออัพเดทรูปแบบการเขียนโค้ดของคำสั่ง 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 ไปเลย น่าจะสะดวกกว่านะ ฮ่าๆ




เหล่าพันธมิตรแอนดรอยด์

Devahoy Layer Net NuuNeoI The Cheese Factory Somkiat CC Mart Routine Artit-K Arnondora Kamonway Try to be android developer Oatrice Benz Nest Studios Kotchaphan@Medium Jirawatee@Medium Travispea@Medium