Codelab นี้เป็นส่วนหนึ่งของหลักสูตรหลักพื้นฐานของ Android Kotlin คุณจะได้รับประโยชน์สูงสุดจากหลักสูตรนี้หากทำตาม Codelab ตามลำดับ Codelab ของหลักสูตรทั้งหมดแสดงอยู่ในหน้า Landing Page ของ Codelab หลักพื้นฐานของ Android Kotlin
บทนำ
แอปส่วนใหญ่ที่ใช้รายการและตารางกริดซึ่งแสดงรายการจะอนุญาตให้ผู้ใช้โต้ตอบกับรายการ การแตะรายการจากลิสต์และดูรายละเอียดของรายการเป็นกรณีการใช้งานที่พบบ่อยมากสําหรับการโต้ตอบประเภทนี้ หากต้องการดำเนินการนี้ คุณสามารถเพิ่มเครื่องมือฟังการคลิกที่ตอบสนองต่อการแตะรายการของผู้ใช้โดยแสดงมุมมองรายละเอียด
ใน Codelab นี้ คุณจะเพิ่มการโต้ตอบลงใน RecyclerView โดยต่อยอดจากแอปติดตามการนอนหลับเวอร์ชันขยายจาก Codelab ชุดก่อนหน้า
สิ่งที่คุณควรทราบอยู่แล้ว
- การสร้างอินเทอร์เฟซผู้ใช้พื้นฐานโดยใช้กิจกรรม Fragment และมุมมอง
- การไปยังส่วนย่อยต่างๆ และการใช้
safeArgsเพื่อส่งข้อมูลระหว่างส่วนย่อย - ดูโมเดล โรงงานโมเดล การแปลง และ
LiveDataรวมถึง Observer ของโมเดล - วิธีสร้าง
Roomฐานข้อมูล สร้างออบเจ็กต์การเข้าถึงข้อมูล (DAO) และกำหนดเอนทิตี - วิธีใช้โครูทีนสำหรับฐานข้อมูลและงานอื่นๆ ที่ใช้เวลานาน
- วิธีใช้
RecyclerViewพื้นฐานกับAdapter,ViewHolderและเลย์เอาต์รายการ - วิธีใช้การเชื่อมโยงข้อมูลสำหรับ
RecyclerView - วิธีสร้างและใช้อะแดปเตอร์การเชื่อมโยงเพื่อเปลี่ยนรูปแบบข้อมูล
- วิธีใช้
GridLayoutManager
สิ่งที่คุณจะได้เรียนรู้
- วิธีทำให้รายการใน
RecyclerViewคลิกได้ ใช้เครื่องมือฟังการคลิกเพื่อไปยังมุมมองรายละเอียดเมื่อมีการคลิกรายการ
สิ่งที่คุณต้องดำเนินการ
- สร้างต่อจากแอป TrackMySleepQuality เวอร์ชันขยายจากโค้ดแล็บก่อนหน้าในชุดนี้
- เพิ่มเครื่องมือฟังการคลิกลงในรายการและเริ่มฟังการโต้ตอบของผู้ใช้ เมื่อแตะรายการ ระบบจะเรียกใช้การนำทางไปยัง Fragment ที่มีรายละเอียดเกี่ยวกับรายการที่คลิก โค้ดเริ่มต้นมีโค้ดสำหรับรายละเอียด Fragment รวมถึงโค้ดการนำทาง
แอปติดตามการนอนหลับเริ่มต้นมี 2 หน้าจอซึ่งแสดงด้วย Fragment ดังที่แสดงในรูปภาพด้านล่าง
|
|
หน้าจอแรกที่แสดงทางด้านซ้ายมีปุ่มสำหรับเริ่มและหยุดการติดตาม หน้าจอจะแสดงข้อมูลการนอนหลับบางส่วนของผู้ใช้ ปุ่มล้างจะลบข้อมูลทั้งหมดที่แอปเก็บรวบรวมไว้สำหรับผู้ใช้ออกอย่างถาวร หน้าจอที่ 2 ซึ่งแสดงทางด้านขวาใช้สำหรับเลือกคะแนนคุณภาพการนอนหลับ
แอปนี้ใช้สถาปัตยกรรมที่เรียบง่ายพร้อมตัวควบคุม UI, โมเดลมุมมอง และ LiveData รวมถึงฐานข้อมูล Room เพื่อจัดเก็บข้อมูลการนอนหลับ

ในโค้ดแล็บนี้ คุณจะเพิ่มความสามารถในการตอบสนองเมื่อผู้ใช้แตะรายการในตารางกริด ซึ่งจะแสดงหน้าจอรายละเอียดเหมือนกับหน้าจอด้านล่าง โค้ดสำหรับหน้าจอนี้ (Fragment, ViewModel และการนำทาง) จะมาพร้อมกับแอปเริ่มต้น และคุณจะใช้กลไกการจัดการการคลิก

ขั้นตอนที่ 1: ดาวน์โหลดแอปเริ่มต้น
- ดาวน์โหลดโค้ด RecyclerViewClickHandler-Starter จาก GitHub แล้วเปิดโปรเจ็กต์ใน Android Studio
- สร้างและเรียกใช้แอปติดตามการนอนหลับเริ่มต้น
[ไม่บังคับ] อัปเดตแอปหากต้องการใช้แอปจากโค้ดแล็บก่อนหน้า
หากคุณจะทำงานจากแอปเริ่มต้นที่ระบุไว้ใน GitHub สำหรับโค้ดแล็บนี้ ให้ข้ามไปยังขั้นตอนถัดไป
หากต้องการใช้แอปติดตามการนอนหลับที่คุณสร้างขึ้นใน Codelab ก่อนหน้าต่อไป ให้ทำตามวิธีการด้านล่างเพื่ออัปเดตแอปที่มีอยู่ให้มีโค้ดสำหรับรายละเอียดหน้าจอ Fragment
- แม้ว่าคุณจะใช้แอปที่มีอยู่ต่อไป แต่ให้รับโค้ด RecyclerViewClickHandler-Starter จาก GitHub เพื่อให้คุณคัดลอกไฟล์ได้
- คัดลอกไฟล์ทั้งหมดในแพ็กเกจ
sleepdetail - ใน
layoutโฟลเดอร์ ให้คัดลอกไฟล์fragment_sleep_detail.xml - คัดลอกเนื้อหาที่อัปเดตของ
navigation.xmlซึ่งจะเพิ่มการนำทางสำหรับsleep_detail_fragment - ใน
databaseแพ็กเกจSleepDatabaseDaoให้เพิ่มเมธอดgetNightWithId()ใหม่
/**
* Selects and returns the night with given nightId.
*/
@Query("SELECT * from daily_sleep_quality_table WHERE nightId = :key")
fun getNightWithId(key: Long): LiveData<SleepNight>- ใน
res/values/stringsให้เพิ่มทรัพยากรสตริงต่อไปนี้
<string name="close">Close</string>- ล้างและสร้างแอปใหม่เพื่ออัปเดตการเชื่อมโยงข้อมูล
ขั้นตอนที่ 2: ตรวจสอบโค้ดสำหรับหน้าจอรายละเอียดการนอนหลับ
ในโค้ดแล็บนี้ คุณจะใช้ตัวแฮนเดิลการคลิกที่จะไปยัง Fragment ที่แสดงรายละเอียดเกี่ยวกับคืนที่นอนหลับที่คลิก โค้ดเริ่มต้นมี Fragment และกราฟการนำทางสำหรับ SleepDetailFragment อยู่แล้ว เนื่องจากมีโค้ดจำนวนมาก และ Fragment กับการนำทางไม่ได้เป็นส่วนหนึ่งของ Codelab นี้ ทำความคุ้นเคยกับโค้ดต่อไปนี้
- ค้นหาแพ็กเกจ
sleepdetailในแอป แพ็กเกจนี้มี Fragment, ViewModel และ ViewModelFactory สำหรับ Fragment ที่แสดงรายละเอียดการนอนหลับ 1 คืน - ในแพ็กเกจ
sleepdetailให้เปิดและตรวจสอบโค้ดสำหรับSleepDetailViewModelโมเดลมุมมองนี้ใช้คีย์สำหรับSleepNightและ DAO ในตัวสร้าง
เนื้อหาของคลาสมีโค้ดเพื่อรับSleepNightสำหรับคีย์ที่ระบุ และตัวแปรnavigateToSleepTrackerเพื่อควบคุมการนำทางกลับไปยังSleepTrackerFragmentเมื่อกดปุ่มปิด
ฟังก์ชันgetNightWithId()จะแสดงผลLiveData<SleepNight>และกำหนดไว้ในSleepDatabaseDao(ในแพ็กเกจdatabase) - ในแพ็กเกจ
sleepdetailให้เปิดและตรวจสอบโค้ดสำหรับSleepDetailFragmentโปรดสังเกตการตั้งค่าการเชื่อมโยงข้อมูล, View Model และ Observer สำหรับการนำทาง - ในแพ็กเกจ
sleepdetailให้เปิดและตรวจสอบโค้ดสำหรับSleepDetailViewModelFactory - ตรวจสอบ
fragment_sleep_detail.xmlในโฟลเดอร์เลย์เอาต์ โปรดสังเกตตัวแปรsleepDetailViewModelที่กำหนดไว้ในแท็ก<data>เพื่อรับข้อมูลที่จะแสดงในแต่ละมุมมองจาก View Model
เลย์เอาต์มีConstraintLayoutที่มีImageViewสำหรับคุณภาพการนอนหลับTextViewสำหรับการให้คะแนนคุณภาพTextViewสำหรับระยะเวลาการนอนหลับ และButtonเพื่อปิดรายละเอียด Fragment - เปิดไฟล์
navigation.xmlสำหรับsleep_tracker_fragmentให้สังเกตการดำเนินการใหม่สำหรับsleep_detail_fragment
การดำเนินการใหม่action_sleep_tracker_fragment_to_sleepDetailFragmentคือการไปยังส่วนต่างๆ จาก Fragment เครื่องมือติดตามการนอนหลับไปยังหน้าจอรายละเอียด
ในงานนี้ คุณจะอัปเดต RecyclerView เพื่อตอบสนองต่อการแตะของผู้ใช้โดยแสดงหน้าจอรายละเอียดสำหรับรายการที่แตะ
การรับและการจัดการคลิกเป็นงาน 2 ส่วน โดยก่อนอื่นคุณต้องรับฟังและรับคลิก รวมถึงพิจารณาว่ามีการคลิกรายการใด จากนั้นคุณต้องตอบสนองต่อการคลิกด้วยการดำเนินการ
แล้วที่ไหนเหมาะที่สุดที่จะเพิ่มเครื่องมือฟังการคลิกสำหรับแอปนี้
SleepTrackerFragmentมีมุมมองมากมาย ดังนั้นการฟังเหตุการณ์คลิกที่ระดับ Fragment จะไม่บอกว่ามีการคลิกรายการใด และจะไม่บอกด้วยว่าเป็นการคลิกรายการหรือองค์ประกอบ UI อื่นๆ- การฟังที่ระดับ
RecyclerViewทำให้ยากที่จะระบุได้อย่างแม่นยำว่าผู้ใช้คลิกรายการใดในรายการ - อัตราที่ดีที่สุดในการรับข้อมูลเกี่ยวกับรายการที่คลิกคือในออบเจ็กต์
ViewHolderเนื่องจากแสดงถึงรายการในลิสต์ 1 รายการ
แม้ว่า ViewHolder จะเป็นที่ที่เหมาะสำหรับการฟังการคลิก แต่โดยปกติแล้วไม่ใช่ที่ที่เหมาะสมในการจัดการการคลิก แล้วที่ใดคือที่ที่ดีที่สุดในการจัดการคลิก
Adapterจะแสดงรายการข้อมูลในมุมมองเพื่อให้คุณจัดการการคลิกในอแดปเตอร์ได้ อย่างไรก็ตาม หน้าที่ของ Adapter คือการปรับข้อมูลเพื่อแสดง ไม่ใช่การจัดการตรรกะของแอป- โดยปกติแล้ว คุณควรจัดการการคลิกใน
ViewModelเนื่องจากViewModelมีสิทธิ์เข้าถึงข้อมูลและตรรกะในการพิจารณาสิ่งที่ต้องเกิดขึ้นเพื่อตอบสนองต่อการคลิก
ขั้นตอนที่ 1: สร้างเครื่องมือฟังการคลิกและเรียกใช้จากเลย์เอาต์ของรายการ
- ในโฟลเดอร์
sleeptrackerให้เปิด SleepNightAdapter.kt - ที่ส่วนท้ายของไฟล์ ในระดับบนสุด ให้สร้างคลาส Listener ใหม่
SleepNightListener
class SleepNightListener() {
}- เพิ่ม
onClick()ฟังก์ชันภายในSleepNightListenerคลาส เมื่อมีการคลิกมุมมองที่แสดงรายการ ระบบจะเรียกใช้onClick()ฟังก์ชันนี้ (คุณจะตั้งค่าพร็อพเพอร์ตี้android:onClickของข้อมูลพร็อพเพอร์ตี้ในภายหลังเป็นฟังก์ชันนี้)
class SleepNightListener() {
fun onClick() =
}- เพิ่มอาร์กิวเมนต์ฟังก์ชัน
nightของประเภทSleepNightไปยังonClick()มุมมองทราบว่ากำลังแสดงรายการใด และต้องส่งต่อข้อมูลดังกล่าวเพื่อจัดการการคลิก
class SleepNightListener() {
fun onClick(night: SleepNight) =
}- หากต้องการกำหนดว่า
onClick()ทำอะไร ให้ระบุการเรียกกลับclickListenerในตัวสร้างของSleepNightListenerแล้วกำหนดให้onClick()
การตั้งชื่อ Lambda ที่จัดการการคลิกclickListenerจะช่วยให้ติดตามได้เมื่อมีการส่งผ่านระหว่างคลาส การเรียกกลับclickListenerต้องการเพียงnight.nightIdเพื่อเข้าถึงข้อมูลจากฐานข้อมูลSleepNightListenerคลาสที่เสร็จสมบูรณ์แล้วควรมีลักษณะเหมือนโค้ดด้านล่าง
class SleepNightListener(val clickListener: (sleepId: Long) -> Unit) {
fun onClick(night: SleepNight) = clickListener(night.nightId)
}- เปิด list_item_sleep_night.xml.
- ภายในบล็อก
dataให้เพิ่มตัวแปรใหม่เพื่อให้คลาสSleepNightListenerพร้อมใช้งานผ่านการเชื่อมโยงข้อมูล ตั้ง<variable>ใหม่เป็นnameของclickListener.ตั้งค่าtypeเป็นชื่อที่สมบูรณ์ของคลาสcom.example.android.trackmysleepquality.sleeptracker.SleepNightListenerดังที่แสดงด้านล่าง ตอนนี้คุณเข้าถึงฟังก์ชันonClick()ในSleepNightListenerจากเลย์เอาต์นี้ได้แล้ว
<variable
name="clickListener"
type="com.example.android.trackmysleepquality.sleeptracker.SleepNightListener" />- หากต้องการฟังการคลิกส่วนใดส่วนหนึ่งของรายการนี้ ให้เพิ่มแอตทริบิวต์
android:onClickลงในConstraintLayout
ตั้งค่าแอตทริบิวต์เป็นclickListener:onClick(sleep)โดยใช้ Lambda การเชื่อมโยงข้อมูล ดังที่แสดงด้านล่าง
android:onClick="@{() -> clickListener.onClick(sleep)}"ขั้นตอนที่ 2: ส่งเครื่องมือฟังการคลิกไปยังตัวยึดมุมมองและออบเจ็กต์การเชื่อมโยง
- เปิด SleepNightAdapter.kt
- แก้ไขตัวสร้างของคลาส
SleepNightAdapterเพื่อรับval clickListener: SleepNightListenerเมื่ออะแดปเตอร์เชื่อมโยงViewHolderจะต้องระบุเครื่องมือฟังการคลิกนี้
class SleepNightAdapter(val clickListener: SleepNightListener):
ListAdapter<SleepNight, SleepNightAdapter.ViewHolder>(SleepNightDiffCallback()) {- ใน
onBindViewHolder()ให้อัปเดตการเรียกไปยังholder.bind()เพื่อส่งต่อ Listener การคลิกไปยังViewHolderด้วย คุณจะได้รับข้อผิดพลาดของคอมไพเลอร์เนื่องจากคุณเพิ่มพารามิเตอร์ลงในการเรียกฟังก์ชัน
holder.bind(getItem(position)!!, clickListener)- เพิ่มพารามิเตอร์
clickListenerลงในbind()โดยวางเคอร์เซอร์บนข้อผิดพลาด แล้วกดAlt+Enter(Windows) หรือOption+Enter(Mac) บนข้อผิดพลาดเพื่อดูรายละเอียด ดังที่แสดงในภาพหน้าจอด้านล่าง
- ในคลาส
ViewHolderภายในฟังก์ชันbind()ให้กำหนด Listener การคลิกให้กับออบเจ็กต์bindingคุณเห็นข้อผิดพลาดเนื่องจากต้องอัปเดตออบเจ็กต์การเชื่อมโยง
binding.clickListener = clickListener- หากต้องการอัปเดตการเชื่อมโยงข้อมูล ให้ล้างและสร้างใหม่โปรเจ็กต์ (คุณอาจต้องล้างแคชด้วย) ดังนั้น คุณจึงนำเครื่องมือฟังการคลิกจากตัวสร้างอแดปเตอร์ และส่งไปยังตัวยึดมุมมองและไปยังออบเจ็กต์การเชื่อมโยง
ขั้นตอนที่ 3: แสดงข้อความป๊อปอัปเมื่อแตะรายการ
ตอนนี้คุณมีโค้ดที่ใช้บันทึกการคลิกแล้ว แต่ยังไม่ได้ติดตั้งใช้งานสิ่งที่เกิดขึ้นเมื่อมีการแตะรายการในลิสต์ การตอบกลับที่ง่ายที่สุดคือการแสดงข้อความป๊อปอัปที่แสดง nightId เมื่อมีการคลิกรายการ ซึ่งจะยืนยันว่าเมื่อมีการคลิกรายการ ระบบจะบันทึกและส่งต่อ nightId ที่ถูกต้อง
- เปิด SleepTrackerFragment.kt
- ใน
onCreateView()ให้ค้นหาตัวแปรadapterโปรดสังเกตว่าระบบแสดงข้อผิดพลาดเนื่องจากตอนนี้คาดหวังพารามิเตอร์ Listener การคลิก - กำหนดเครื่องมือฟังการคลิกโดยส่งผ่าน Lambda ไปยัง
SleepNightAdapterLambda อย่างง่ายนี้จะแสดงข้อความโทสต์ที่แสดงnightIdดังที่แสดงด้านล่าง คุณจะต้องนำเข้าToastคำจำกัดความที่อัปเดตแล้วฉบับสมบูรณ์มีดังนี้
val adapter = SleepNightAdapter(SleepNightListener { nightId ->
Toast.makeText(context, "${nightId}", Toast.LENGTH_LONG).show()
})- เรียกใช้แอป แตะรายการ และตรวจสอบว่ารายการแสดงข้อความป๊อปอัปพร้อม
nightIdที่ถูกต้อง เนื่องจากรายการมีค่าnightIdเพิ่มขึ้น และแอปจะแสดงคืนล่าสุดก่อน รายการที่มีค่าnightIdต่ำสุดจึงอยู่ด้านล่างของรายการ
ในงานนี้ คุณจะเปลี่ยนลักษณะการทำงานเมื่อมีการคลิกรายการใน RecyclerView เพื่อให้แอปไปยังรายละเอียด Fragment ที่แสดงข้อมูลเพิ่มเติมเกี่ยวกับคืนที่คลิกแทนที่จะแสดงข้อความ Toast
ขั้นตอนที่ 1: ไปที่หน้าเว็บเมื่อคลิก
ในขั้นตอนนี้ แทนที่จะแสดงเพียงข้อความป๊อปอัป คุณจะเปลี่ยน Lambda ของเครื่องมือฟังการคลิกใน onCreateView() ของ SleepTrackerFragment เพื่อส่ง nightId ไปยัง SleepTrackerViewModel และทริกเกอร์การนำทางไปยัง SleepDetailFragment
กำหนดฟังก์ชันตัวแฮนเดิลการคลิก
- เปิด SleepTrackerViewModel.kt
- ภายใน
SleepTrackerViewModelให้กําหนดonSleepNightClicked()ฟังก์ชันตัวแฮนเดิลการคลิกที่ส่วนท้าย
fun onSleepNightClicked(id: Long) {
}- ภายใน
onSleepNightClicked()ให้ทริกเกอร์การนำทางโดยตั้งค่า_navigateToSleepDetailเป็นidที่ส่งมาของคืนที่คลิก
fun onSleepNightClicked(id: Long) {
_navigateToSleepDetail.value = id
}- นำ
_navigateToSleepDetailมาใช้ กำหนดprivate MutableLiveDataสำหรับสถานะการนำทางเช่นเดียวกับที่เคยทำ และมีvalที่รับได้แบบสาธารณะ
private val _navigateToSleepDetail = MutableLiveData<Long>()
val navigateToSleepDetail
get() = _navigateToSleepDetail- กำหนดวิธีการเรียกใช้หลังจากที่แอปนำทางเสร็จแล้ว ตั้งชื่อว่า
onSleepDetailNavigated()และตั้งค่าเป็นnull
fun onSleepDetailNavigated() {
_navigateToSleepDetail.value = null
}เพิ่มโค้ดเพื่อเรียกตัวแฮนเดิลการคลิก
- เปิด SleepTrackerFragment.kt แล้วเลื่อนลงไปที่โค้ดที่สร้างอแดปเตอร์และกำหนด
SleepNightListenerเพื่อแสดงข้อความ Toast
val adapter = SleepNightAdapter(SleepNightListener { nightId ->
Toast.makeText(context, "${nightId}", Toast.LENGTH_LONG).show()
})- เพิ่มโค้ดต่อไปนี้ใต้ข้อความป๊อปอัปเพื่อเรียกตัวแฮนเดิลการคลิก
onSleepNighClicked()ในsleepTrackerViewModelเมื่อมีการแตะรายการ ส่งในnightIdเพื่อให้ ViewModel รู้ว่าควรรับคืนการนอนหลับคืนใด ซึ่งจะทำให้เกิดข้อผิดพลาดเนื่องจากคุณยังไม่ได้กำหนดonSleepNightClicked()คุณจะเก็บ แสดงความคิดเห็น หรือลบข้อความแจ้งก็ได้ตามต้องการ
sleepTrackerViewModel.onSleepNightClicked(nightId)เพิ่มโค้ดเพื่อสังเกตการคลิก
- เปิด SleepTrackerFragment.kt
- ใน
onCreateView()เหนือประกาศของmanagerให้เพิ่มโค้ดเพื่อสังเกตnavigateToSleepDetailLiveDataใหม่ เมื่อnavigateToSleepDetailเปลี่ยนแปลง ให้ไปที่SleepDetailFragmentโดยส่งnightแล้วเรียกใช้onSleepDetailNavigated()หลังจากนั้น เนื่องจากคุณเคยทำสิ่งนี้ในโค้ดแล็บก่อนหน้านี้แล้ว เราจึงขอเสนอโค้ดดังนี้
sleepTrackerViewModel.navigateToSleepDetail.observe(this, Observer { night ->
night?.let {
this.findNavController().navigate(
SleepTrackerFragmentDirections
.actionSleepTrackerFragmentToSleepDetailFragment(night))
sleepTrackerViewModel.onSleepDetailNavigated()
}
})- เรียกใช้โค้ด คลิกที่รายการ แล้วแอปก็ขัดข้อง
จัดการค่า Null ใน Binding Adapter ดังนี้
- เรียกใช้แอปอีกครั้งในโหมดแก้ไขข้อบกพร่อง แตะรายการ แล้วกรองบันทึกเพื่อแสดงข้อผิดพลาด โดยจะแสดง Stack Trace ซึ่งรวมถึงข้อมูลที่คล้ายกับข้อมูลด้านล่าง
Caused by: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter itemขออภัยที่สแต็กเทรซไม่ได้ระบุอย่างชัดเจนว่าข้อผิดพลาดนี้เกิดขึ้นที่ใด ข้อเสียอย่างหนึ่งของการเชื่อมโยงข้อมูลคือการทำให้แก้ไขข้อบกพร่องของโค้ดได้ยากขึ้น แอปขัดข้องเมื่อคุณคลิกรายการ และโค้ดใหม่มีไว้เพื่อจัดการการคลิกเท่านั้น
อย่างไรก็ตาม กลไกการจัดการคลิกแบบใหม่นี้ทำให้ตอนนี้ Binding Adapter สามารถเรียกใช้ด้วยค่า null สำหรับ item ได้แล้ว โดยเฉพาะอย่างยิ่ง เมื่อแอปเริ่มต้น LiveData จะเริ่มต้นเป็น null คุณจึงต้องเพิ่มการตรวจสอบค่า Null ลงในแต่ละอแดปเตอร์
- ใน
BindingUtils.ktให้เปลี่ยนประเภทอาร์กิวเมนต์itemเป็น Nullable สำหรับ Binding Adapter แต่ละรายการ แล้วห่อเนื้อหาด้วยitem?.let{...}เช่น อะแดปเตอร์สำหรับsleepQualityStringจะมีลักษณะดังนี้ เปลี่ยนอแดปเตอร์อื่นๆ ในลักษณะเดียวกัน
@BindingAdapter("sleepQualityString")
fun TextView.setSleepQualityString(item: SleepNight?) {
item?.let {
text = convertNumericQualityToString(item.sleepQuality, context.resources)
}
}- เรียกใช้แอป แตะรายการ แล้วมุมมองรายละเอียดจะเปิดขึ้น
โปรเจ็กต์ Android Studio: RecyclerViewClickHandler
หากต้องการให้รายการใน RecyclerView ตอบสนองต่อการคลิก ให้แนบเครื่องมือฟังการคลิกกับรายการใน ViewHolder และจัดการการคลิกใน ViewModel
หากต้องการให้รายการใน RecyclerView ตอบสนองต่อการคลิก คุณต้องทำดังนี้
- สร้างคลาส Listener ที่ใช้ Lambda และกำหนดให้กับฟังก์ชัน
onClick()
class SleepNightListener(val clickListener: (sleepId: Long) -> Unit) {
fun onClick(night: SleepNight) = clickListener(night.nightId)
}- ตั้งค่าเครื่องมือฟังการคลิกในมุมมอง
android:onClick="@{() -> clickListener.onClick(sleep)}"- ส่งเครื่องมือฟังการคลิกไปยังตัวสร้างอะแดปเตอร์ ไปยังตัวยึดมุมมอง และเพิ่มลงในออบเจ็กต์การเชื่อมโยง
class SleepNightAdapter(val clickListener: SleepNightListener):
ListAdapter<DataItem, RecyclerView.ViewHolder>(SleepNightDiffCallback()holder.bind(getItem(position)!!, clickListener)binding.clickListener = clickListener- ใน Fragment ที่แสดง RecyclerView ซึ่งคุณสร้าง Adapter ให้กำหนดเครื่องมือฟังการคลิกโดยส่ง Lambda ไปยัง Adapter
val adapter = SleepNightAdapter(SleepNightListener { nightId ->
sleepTrackerViewModel.onSleepNightClicked(nightId)
})- ใช้ตัวแฮนเดิลการคลิกใน ViewModel สําหรับการคลิกรายการในลิสต์ โดยทั่วไปแล้วการคลิกนี้จะทําให้เกิดการไปยังส่วนย่อยรายละเอียด
หลักสูตร Udacity:
เอกสารประกอบสำหรับนักพัฒนาแอป Android
ส่วนนี้แสดงรายการการบ้านที่เป็นไปได้สำหรับนักเรียน/นักศึกษาที่กำลังทำ Codelab นี้เป็นส่วนหนึ่งของหลักสูตรที่สอนโดยผู้สอน ผู้สอนมีหน้าที่ดำเนินการต่อไปนี้
- มอบหมายการบ้านหากจำเป็น
- สื่อสารกับนักเรียนเกี่ยวกับวิธีส่งงานที่ได้รับมอบหมาย
- ให้คะแนนงานการบ้าน
ผู้สอนสามารถใช้คำแนะนำเหล่านี้ได้มากน้อยตามที่ต้องการ และควรมีอิสระในการมอบหมายการบ้านอื่นๆ ที่เห็นว่าเหมาะสม
หากคุณกำลังทำ Codelab นี้ด้วยตนเอง โปรดใช้แบบฝึกหัดเหล่านี้เพื่อทดสอบความรู้ของคุณ
ตอบคำถามต่อไปนี้
คำถามที่ 1
สมมติว่าแอปของคุณมี RecyclerView ที่แสดงรายการในช็อปปิ้งลิสต์ แอปของคุณยังกำหนดคลาสตัวฟังการคลิกด้วย
class ShoppingListItemListener(val clickListener: (itemId: Long) -> Unit) {
fun onClick(cartItem: CartItem) = clickListener(cartItem.itemId)
}คุณจะทำให้ ShoppingListItemListener พร้อมใช้งานกับการเชื่อมโยงข้อมูลได้อย่างไร เลือกหนึ่งรายการ
▢ ในไฟล์เลย์เอาต์ที่มี RecyclerView ที่แสดงรายการช็อปปิ้ง ให้เพิ่มตัวแปร <data> สำหรับ ShoppingListItemListener
▢ ในไฟล์เลย์เอาต์ที่กำหนดเลย์เอาต์สำหรับแถวเดียวในรายการช็อปปิ้ง ให้เพิ่มตัวแปร <data> สำหรับ ShoppingListItemListener
▢ ในคลาส ShoppingListItemListener ให้เพิ่มฟังก์ชันเพื่อเปิดใช้การเชื่อมโยงข้อมูล
fun onBinding (cartItem: CartItem) {dataBindingEnable(true)}▢ ในคลาส ShoppingListItemListener ภายในฟังก์ชัน onClick() ให้เพิ่มการเรียกเพื่อเปิดใช้การเชื่อมโยงข้อมูล
fun onClick(cartItem: CartItem) = {
clickListener(cartItem.itemId)
dataBindingEnable(true)
}คำถามที่ 2
คุณจะเพิ่มแอตทริบิวต์ android:onClick ที่ทำให้สินค้าใน RecyclerView ตอบสนองต่อการคลิกได้ที่ใด เลือกได้มากกว่า 1 ข้อ
▢ ในไฟล์เลย์เอาต์ที่แสดง RecyclerView ให้เพิ่มลงใน <androidx.recyclerview.widget.RecyclerView>
▢ เพิ่มลงในไฟล์เลย์เอาต์ของรายการในแถว หากต้องการให้ทั้งรายการคลิกได้ ให้เพิ่มรายการลงในมุมมองระดับบนที่มีรายการในแถว
▢ เพิ่มลงในไฟล์เลย์เอาต์ของรายการในแถว หากต้องการให้ TextView รายการเดียวในรายการคลิกได้ ให้เพิ่มลงใน <TextView>
▢ เพิ่มลงในไฟล์เลย์เอาต์สำหรับ MainActivity เสมอ
เริ่มบทเรียนถัดไป:

