ชาว Android Kotlin Developer มาใช้ View Binding กันเถอะ

Android Jan 29, 2021

ใน Android Jetpack มีตัวนึง ชื่อว่า View Binding (ไม่ใช่ Data Binding เน้อ) เอามาใช้แทน Kotlin Synthetic ได้ ลดปัญหาที่เกิดจากการใช้ view ที่มี id ชื่อเดียวกันนั่นเอง

ซึ่งบางครั้งเราก็ได้อ้างอิง view id และ layout ที่ถูกต้องไปแล้ว แต่ดันหาไม่เจอซะงั้น ทำให้แอพแคลช แล้วเรางงว่าเกิดจากอิหยังอะเนี่ยย โอ่ยยยยย เจ็บไปท้างหัวจายตะไมยางทน เจอบัคอีกกี่หนนะคนจายร้ายยยยย~~ เพราะไม่รู้จะแก้ยังไงนี่สิ

ที่มาของการใช้ View Binding ตัวนี้ก็คือ ในทีมแนะนำให้ใช้เพื่อแก้ความเจ็บปวด และสามารถตั้งชื่อ id ของ view ซํ้าได้ แม้อยู่คนละ layout ก็ตาม ทำให้เราไม่เจอ app crash ที่หา view นั้นใน layout ที่เราต้องการไม่เจอนั่นเอง

โดยเจ้า View Binding ตัวนี้นั้นที่อยู่ใน Android Jetpacks ใช้แทน findViewById() ที่เราเคยใช้มาเมื่ออดีตกาลนั่นเอง

ส่วนความแตกต่างของการทำ View Binding แต่ละแบบ สามารถอ่านที่บล็อกพี่เอกได้เลยจ้า เขียนละเอียดสุดๆ อยากให้อ่านทำความเข้าใจก่อนใช้งานจริงนะ

View Binding บนแอนดรอยด์ทำแบบไหนได้บ้างนะ?
เจ้าของบล็อกเชื่อว่าคงไม่มีนักพัฒนาคนไหนที่ไม่รู้จักกับการทำ View Binding บนแอนดรอยด์ เพราะมันคือขั้นตอนพื้นฐานที่นักพัฒนาทุกคนต้องทำ เพื่อให้โค้ด Java หรือ Kotlin ในโปรเจคแอนดรอยด์สามารถเรียกใช้งาน View ที่อยู่ใน Layout XML

ย้อนความในอดีตที่ไม่ไกลมากเกี่ยวกับการ binding

ในที่นี้เราจะพูดถึง 2 แบบในบล็อกนี้กัน ก็คือ Kotlin Synthetic กับ View Binding เนอะ

เมื่อเราเป็น Android Kotlin Developer เราเริ่มจะไม่ใช้สิ่งที่เรียกว่า findViewById() กันแล้ว แหะๆ (ขอไม่เอ่ยถึงมีดตัดเนยนะ) เราเลยใช้ Kotlin Symthetic แทน โดยก่อนอื่นนั้น เราก็ต้องลง plug-in ของ Kotlin ที่ Android Studio ของเรา และเพิ่ม dependency ของ Kotlin ลงไปใน build.gradle ของ module แบบนี้

implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"

ในการสร้าง layout นั้น เมื่อก่อนเราจะตั้งชื่อ view id แบบมี underscore เนอะ เรียกว่า snake case เช่น image_avatar พอมาเป็น Android Kotlin Developer แล้วไซร้ เราเลยต้องตั้งชื่อเป็น camel case กันเพื่อความสวยงามเมื่อนำไปใช้ในโค้ดนั่นเอง เช่น imageAvatar สมมุติว่า layout นี้นั้นชื่อว่า fragment_profile แล้วกันเนอะ

แล้วเราก็นำเจ้า view id ไปใช้ เราก็สามารถใช้ชื่อ view id ของเราได้เลย โดยมันจะอ้างอิงจาก synthetic ของ layout นั้นๆมา เมื่อกี้บอกว่าชื่อ fragment_profile ก็จะเป็นแบบนี้

kotlinx.android.synthetic.main.fragment_profile

วันดีคืนร้าย พอดีว่าแอพของเราใช้ view id ของ ImageView ต่างๆว่า imageAvatar ในหลายๆที่ เนื่องจากแอพนี้เนี่ยมีเกี่ยวกับการแสดง user ในหลายๆที่ พอมารันในแอพเท่านั้นแหละ พบว่า อ้าว แอพแคลชเพราะหาชื่อ id ของ view ไม่เจอ

(จะแปะรูปแต่หา error แบบนี้ไม่เจอหล่ะ อ่ะช่วยจินตนาการหน่อยน้าาาา)

อ่ะเข้าไปดูโค้ดเราหน่อย อ่ะก็ถูก layout แล้วนี่หว่า อ่ะชื่อก็ถูก แล้วช้านทำอะไรผิดปายยยย~~ เป็นคำถามที่หาคำตอบไม่ได้นานมากแล้ว ตั้งแต่เริ่มเขียน Kotlin แรกๆ เนื่องจากเจอ crashlytics ประมาณนี้บ่อยมาก แล้วก็หาคำตอบไม่เจอว่าเกิดจากอะไร จนมาเจอเรื่อง View Binding เลยอ๋อเลย หลังจากหาคำตอบมาประมาณสองปี ...

แล้วเราจะใช้ View Binding ยังไงดีหล่ะ?

เริ่มจากการ setup ที่ build.gradle ของ module ไปแบบนี้

android {
    ...
    viewBinding {
        enabled = true
    }
}

หลังจากที่เราสร้าง layout ของเราไปแล้วนั้น มาที่ class View ของเรา แล้วทำการประกาศตัวแปร binding ซะ

// สำหรับ Activity
private lateinit var binding: ActivityMainBinding

// สำหรับ Fragment
private lateinit var binding: FragmentMainBinding

โดย type ของตัวแปร binding นี้ จะเป็นไปตามชื่อของ layout ที่อ้างอิงกับ view ของเรา เช่น เรากำลังทำที่หน้า MainFragment อยู่ มี layout ชื่อว่า fragment_main ดังนั้นมันจะเป็นชื่อแบบ camel case โดยเป็นชื่อ layout แล้วตามมาด้วย Binding นั่นเอง

หลังจากประกาศตัวแปรเรียบร้อยแล้ว เราจะทำการใส่ค่าให้มันกัน ที่ onCreate() สำหรับ Activity เพื่อ inflate จาก layout มา และ set view layout เป็น binding.root

// for activity
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)
}

สำหรับ Fragment เราจะ inflate layout ที่ onCreateView และทำการ return binding.root จ้า

// for fragment
override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?,
): View? {
    binding = FragmentMainBinding.inflate(inflater, container, false)
    return binding.root
}

การใช้งาน เรียก id ของ view โดยผ่านตัวแปร binding นั่นเอง

เช่น เราอยากให้ text แสดงอะไรสักอย่างนึง ปกติที่เราใช้ Kotlin Synthetic เป็นแบบนี้เนอะ

textviewUserName.text = "MikkiPastel"

ตอนนี้ที่ใช้ View Binding ก็คือ เอาชื่อตัวแปร binding ที่ทำไว้ ใส่ไว้หน้าชื่อ view ที่เราต้องการ

binding.textviewUserName.text = "MikkiPastel"

และอย่าลืมลบ Kotlin Synthetic ออกด้วยนะจ๊ะ เดี๋ยวก็ไม่ได้ใช้ View Binding อย่างเต็มที่น้าา

// สำหรับ Activity
import kotlinx.android.synthetic.main.activity_main.*

// สำหรับ Fragment
import kotlinx.android.synthetic.main.fragment_main.*

เท่านี้ก็ใช้งานได้เรียบร้อยจบปิ้งแล้วจ้า

ปล. ถ้า view นั้นใช้หลาย layout ก็ สร้างตัวแปร binding เพิ่มมาอีกนั่นแหละ เพราะมันคนละหน้ากันนี่เนอะ

ข้อจำกัด

ข้อจำกัดของ View Binding ที่ไม่สามารถใช้กับ layout ที่ไม่สามารถใช้ dynamic UI ได้โดยตรงจาก XML และ two-way data binding นั่นเอง ซึ่งทั้งสองอันนั้นวิธีแบบ Data Binding ใช้ได้จ้า

https://developer.android.com/topic/libraries/view-binding#data-binding

ทั้งนี้ทั้งนั้นก็ขึ้นอยู่กับทีมว่าจะตัดสินใจอะไรกันยังไงหล่ะเนอะ :D แต่ส่วนใหญ่ไม่น่าติด layout ที่ตรงกับข้อจำกัดนี้แหละ

Reference จ้า

อันนี้เกี่ยวกับ View Binding เลย เนื้อหากับที่ทำกันก็ตามๆนี้เลย

View binding | Android Developers
https://developer.android.com/topic/libraries/view-binding

อันนี้คือไปหาว่ามา วิธีการตั้งชื่อตัวแปรที่มี underscore เรียกว่าอะไรน้าา ก็เลยไปเจอบล็อกนี้มาเนอะ เผื่อใครสนใจเรื่องมาตรฐานการตั้งชื่อตัวแปรก็เอาไปอ่านต่อกันได้

มาตรฐานการตั้งชื่อตัวแปร (Naming Convention)
หัวข้อนี้อาจทำให้หลายคนสงสัยว่า ผมเขียนขึ้นมาทำไม หลายๆคนที่ได้เรียนวิชา Programming ต่างๆก็คงถูกสอนกันมาอยู่แล้วว่า การตั้งชื่อตั...

download แอพอ่านบล็อกใหม่ของเราได้ที่นี่

MikkiPastel - Apps on Google Play
First application from “MikkiPastel” on play store beta feature- read blog from https://www.mikkipastel.com by this application- read blog content by chrome custom tab- update or refresh new content by pull to refresh- share content to social network
https://play.google.com/store/apps/details?id=com.mikkipastel.blog

ติดตามข่าวสารและบทความใหม่ๆได้ที่

อย่าลืมกด like กด share บทความกันด้วยนะคะ :)

Posted by MikkiPastel on Sunday, 10 December 2017

และช่องทางใหม่ใน Twiter จ้า

Tags

Minseo Chayabanjonglerd

I am a full-time Android Developer and part-time contributor with developer community and web3 world, who believe people have hard skills and soft skills to up-skill to da moon.