Codelab นี้เป็นส่วนหนึ่งของหลักสูตรหลักพื้นฐานของ Android Kotlin คุณจะได้รับประโยชน์สูงสุดจากหลักสูตรนี้หากทำตาม Codelab ตามลำดับ Codelab ของหลักสูตรทั้งหมดแสดงอยู่ในหน้า Landing Page ของ Codelab หลักพื้นฐานของ Android Kotlin
บทนำ
Codelab นี้จะสรุปวิธีใช้ ViewModel
และ Fragment ร่วมกันเพื่อติดตั้งใช้งานการนำทาง โปรดทราบว่าเป้าหมายคือการใส่ตรรกะของเมื่อเพื่อไปยังส่วนต่างๆ ใน ViewModel
แต่ให้กำหนดเส้นทางใน Fragment และไฟล์การนำทาง คุณใช้โมเดลมุมมอง Fragment LiveData
และ Observer เพื่อให้บรรลุเป้าหมายนี้
Codelab จบลงด้วยการแสดงวิธีที่ชาญฉลาดในการติดตามสถานะปุ่มด้วยโค้ดที่น้อยที่สุด เพื่อให้แต่ละปุ่มเปิดใช้และคลิกได้เฉพาะเมื่อผู้ใช้ควรแตะปุ่มนั้น
สิ่งที่คุณควรทราบอยู่แล้ว
คุณควรคุ้นเคยกับสิ่งต่อไปนี้
- การสร้างอินเทอร์เฟซผู้ใช้ (UI) พื้นฐานโดยใช้กิจกรรม Fragment และมุมมอง
- การไปยังส่วนย่อยต่างๆ และการใช้
safeArgs
เพื่อส่งข้อมูลระหว่างส่วนย่อย - ดูโมเดล โรงงานโมเดล การแปลง และ
LiveData
รวมถึง Observer ของโมเดล - วิธีสร้าง
Room
ฐานข้อมูล สร้างออบเจ็กต์การเข้าถึงข้อมูล (DAO) และกำหนดเอนทิตี - วิธีใช้โครูทีนสำหรับการโต้ตอบกับฐานข้อมูลและงานอื่นๆ ที่ใช้เวลานาน
สิ่งที่คุณจะได้เรียนรู้
- วิธีอัปเดตบันทึกคุณภาพการนอนหลับที่มีอยู่ในฐานข้อมูล
- วิธีใช้
LiveData
เพื่อติดตามสถานะปุ่ม - วิธีแสดงแถบแสดงข้อความสั้นๆ เพื่อตอบสนองต่อเหตุการณ์
สิ่งที่คุณต้องดำเนินการ
- ขยายแอป TrackMySleepQuality เพื่อรวบรวมคะแนนคุณภาพ เพิ่มคะแนนลงในฐานข้อมูล และแสดงผลลัพธ์
- ใช้
LiveData
เพื่อทริกเกอร์การแสดงแถบแสดงข้อความ - ใช้
LiveData
เพื่อเปิดและปิดใช้ปุ่ม
ใน Codelab นี้ คุณจะได้สร้างการบันทึกคุณภาพการนอนหลับและ UI สุดท้ายของแอป TrackMySleepQuality
แอปมี 2 หน้าจอซึ่งแสดงด้วย Fragment ดังที่แสดงในรูปภาพด้านล่าง
หน้าจอแรกที่แสดงทางด้านซ้ายมีปุ่มสำหรับเริ่มและหยุดการติดตาม หน้าจอจะแสดงข้อมูลการนอนหลับทั้งหมดของผู้ใช้ ปุ่มล้างจะลบข้อมูลทั้งหมดที่แอปเก็บรวบรวมไว้สำหรับผู้ใช้ออกอย่างถาวร
หน้าจอที่ 2 ซึ่งแสดงทางด้านขวาใช้สำหรับเลือกคะแนนคุณภาพการนอนหลับ ในแอป การจัดประเภทจะแสดงเป็นตัวเลข แอปจะแสดงทั้งไอคอนใบหน้าและค่าเทียบเท่าที่เป็นตัวเลขเพื่อวัตถุประสงค์ในการพัฒนา
โฟลว์ของผู้ใช้มีดังนี้
- ผู้ใช้เปิดแอปและเห็นหน้าจอการติดตามการนอนหลับ
- ผู้ใช้แตะปุ่มเริ่ม ซึ่งจะบันทึกเวลาเริ่มต้นและแสดงเวลาดังกล่าว ปุ่มเริ่มจะปิดใช้ และปุ่มหยุดจะเปิดใช้
- ผู้ใช้แตะปุ่มหยุด ซึ่งจะบันทึกเวลาสิ้นสุดและเปิดหน้าจอคุณภาพการนอนหลับ
- ผู้ใช้เลือกไอคอนคุณภาพการนอนหลับ หน้าจอจะปิดลง และหน้าจอการติดตามจะแสดงเวลาสิ้นสุดการนอนหลับและคุณภาพการนอนหลับ ปุ่มหยุดจะปิดใช้และปุ่มเริ่มจะเปิดใช้ แอปพร้อมสำหรับคืนถัดไปแล้ว
- ปุ่มล้างจะเปิดใช้เมื่อใดก็ตามที่มีข้อมูลในฐานข้อมูล เมื่อผู้ใช้แตะปุ่มล้าง ระบบจะลบข้อมูลทั้งหมดของผู้ใช้โดยไม่มีการกู้คืนใดๆ และไม่มีข้อความ "คุณแน่ใจไหม"
แอปนี้ใช้สถาปัตยกรรมที่เรียบง่าย ดังที่แสดงด้านล่างในบริบทของสถาปัตยกรรมแบบเต็ม แอปใช้เฉพาะคอมโพเนนต์ต่อไปนี้
- ตัวควบคุม UI
- ดูโมเดลและ
LiveData
- ฐานข้อมูล Room
Codelab นี้ถือว่าคุณรู้วิธีใช้การนำทางโดยใช้ Fragment และไฟล์การนำทาง เราได้จัดเตรียมโค้ดส่วนใหญ่ไว้ให้คุณแล้วเพื่อช่วยประหยัดเวลา
ขั้นตอนที่ 1: ตรวจสอบโค้ด
- หากต้องการเริ่มต้น ให้ใช้โค้ดของคุณเองจากตอนท้ายของ Codelab สุดท้าย หรือดาวน์โหลดโค้ดเริ่มต้น
- ในโค้ดเริ่มต้น ให้ตรวจสอบ
SleepQualityFragment
คลาสนี้จะขยายเลย์เอาต์ รับแอปพลิเคชัน และส่งคืนbinding.root
- เปิด navigation.xml ในตัวแก้ไขดีไซน์ คุณจะเห็นเส้นทางการนำทางจาก
SleepTrackerFragment
ไปยังSleepQualityFragment
และกลับจากSleepQualityFragment
ไปยังSleepTrackerFragment
- ตรวจสอบโค้ดสำหรับ navigation.xml โดยเฉพาะอย่างยิ่ง ให้มองหา
<argument>
ที่ชื่อsleepNightKey
เมื่อผู้ใช้เปลี่ยนจากSleepTrackerFragment
เป็นSleepQualityFragment,
แอปจะส่งsleepNightKey
ไปยังSleepQualityFragment
สำหรับคืนที่ต้องอัปเดต
ขั้นตอนที่ 2: เพิ่มการนำทางสำหรับการติดตามคุณภาพการนอนหลับ
กราฟการนำทางมีเส้นทางจาก SleepTrackerFragment
ไปยัง SleepQualityFragment
และกลับมาอีกครั้งอยู่แล้ว อย่างไรก็ตาม เรายังไม่ได้เขียนโค้ดตัวแฮนเดิลคลิกที่ใช้การนำทางจาก Fragment หนึ่งไปยัง Fragment ถัดไป คุณเพิ่มโค้ดนั้นใน ViewModel
ได้เลย
ในตัวแฮนเดิลการคลิก คุณจะตั้งค่า LiveData
ที่เปลี่ยนเมื่อต้องการให้แอปไปยังปลายทางอื่น Fragment จะสังเกต LiveData
นี้ เมื่อข้อมูลเปลี่ยนแปลง Fragment จะไปยังปลายทางและบอก ViewModel ว่าดำเนินการเสร็จแล้ว ซึ่งจะรีเซ็ตตัวแปรสถานะ
- เปิด
SleepTrackerViewModel
คุณต้องเพิ่มการนำทางเพื่อให้เมื่อผู้ใช้แตะปุ่มหยุด แอปจะนำทางไปยังSleepQualityFragment
เพื่อรวบรวมคะแนนคุณภาพ - ใน
SleepTrackerViewModel
ให้สร้างLiveData
ที่เปลี่ยนเมื่อคุณต้องการให้แอปไปยังSleepQualityFragment
ใช้การห่อหุ้มเพื่อแสดงเฉพาะเวอร์ชันที่รับได้ของLiveData
ต่อViewModel
คุณวางโค้ดนี้ไว้ที่ใดก็ได้ในระดับบนสุดของเนื้อหาในชั้นเรียน
private val _navigateToSleepQuality = MutableLiveData<SleepNight>()
val navigateToSleepQuality: LiveData<SleepNight>
get() = _navigateToSleepQuality
- เพิ่ม
doneNavigating()
ฟังก์ชันที่รีเซ็ตตัวแปรที่ทริกเกอร์การนำทาง
fun doneNavigating() {
_navigateToSleepQuality.value = null
}
- ในตัวแฮนเดิลการคลิกสำหรับปุ่มหยุด
onStopTracking()
ให้ทริกเกอร์การนำทางไปยังSleepQualityFragment
ตั้งค่าตัวแปร _navigateToSleepQuality
ที่ส่วนท้ายของฟังก์ชันเป็นรายการสุดท้ายภายในบล็อกlaunch{}
โปรดทราบว่าตัวแปรนี้ตั้งค่าเป็นnight
เมื่อตัวแปรนี้มีค่า แอปจะไปยังSleepQualityFragment
พร้อมส่งต่อระยะเวลาที่ค้างคืน
_navigateToSleepQuality.value = oldNight
SleepTrackerFragment
ต้องสังเกต _navigateToSleepQuality
เพื่อให้แอปทราบเวลาที่ควรไปยังส่วนต่างๆ ในSleepTrackerFragment
ในonCreateView()
ให้เพิ่มผู้สังเกตการณ์สำหรับnavigateToSleepQuality()
โปรดทราบว่าการนำเข้าสำหรับรายการนี้ไม่ชัดเจนและคุณต้องนำเข้าandroidx.lifecycle.Observer
sleepTrackerViewModel.navigateToSleepQuality.observe(this, Observer {
})
- ภายในบล็อก Observer ให้ไปที่และส่งรหัสของคืนปัจจุบัน จากนั้นเรียกใช้
doneNavigating()
หากการนำเข้าไม่ชัดเจน ให้นำเข้าandroidx.navigation.fragment.findNavController
night ->
night?.let {
this.findNavController().navigate(
SleepTrackerFragmentDirections
.actionSleepTrackerFragmentToSleepQualityFragment(night.nightId))
sleepTrackerViewModel.doneNavigating()
}
- สร้างและเรียกใช้แอป แตะเริ่ม แล้วแตะหยุด ซึ่งจะนำคุณไปยังหน้าจอ
SleepQualityFragment
หากต้องการกลับ ให้ใช้ปุ่มย้อนกลับของระบบ
ในงานนี้ คุณจะบันทึกคุณภาพการนอนหลับและกลับไปที่ Fragment ของเครื่องมือติดตามการนอนหลับ จอแสดงผลควรอัปเดตโดยอัตโนมัติเพื่อแสดงค่าที่อัปเดตแล้วต่อผู้ใช้ คุณต้องสร้าง ViewModel
และ ViewModelFactory
รวมถึงอัปเดต SleepQualityFragment
ขั้นตอนที่ 1: สร้าง ViewModel และ ViewModelFactory
- ใน
sleepquality
แพ็กเกจ ให้สร้างหรือเปิด SleepQualityViewModel.kt - สร้างคลาส
SleepQualityViewModel
ที่ใช้sleepNightKey
และฐานข้อมูลเป็นอาร์กิวเมนต์ คุณต้องส่งdatabase
จากโรงงานเช่นเดียวกับที่ทำสำหรับSleepTrackerViewModel
นอกจากนี้ คุณยังต้องส่งsleepNightKey
จากการนำทางด้วย
class SleepQualityViewModel(
private val sleepNightKey: Long = 0L,
val database: SleepDatabaseDao) : ViewModel() {
}
- ภายในคลาส
SleepQualityViewModel
ให้กำหนดJob
และuiScope
แล้วลบล้างonCleared()
private val viewModelJob = Job()
private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
override fun onCleared() {
super.onCleared()
viewModelJob.cancel()
}
- หากต้องการกลับไปที่
SleepTrackerFragment
โดยใช้รูปแบบเดียวกันกับด้านบน ให้ประกาศ_navigateToSleepTracker
ใช้navigateToSleepTracker
และdoneNavigating()
private val _navigateToSleepTracker = MutableLiveData<Boolean?>()
val navigateToSleepTracker: LiveData<Boolean?>
get() = _navigateToSleepTracker
fun doneNavigating() {
_navigateToSleepTracker.value = null
}
- สร้างตัวแฮนเดิลการคลิก 1 รายการ
onSetSleepQuality()
สำหรับรูปภาพคุณภาพการนอนหลับทั้งหมดที่จะใช้
ใช้รูปแบบโครูทีนเดียวกันกับในโค้ดแล็บก่อนหน้า
- เปิดใช้โครูทีนใน
uiScope
แล้วเปลี่ยนไปใช้ตัวจัดสรร I/O - รับ
tonight
โดยใช้sleepNightKey
- ตั้งค่าคุณภาพการนอนหลับ
- อัปเดตฐานข้อมูล
- ทริกเกอร์การนำทาง
โปรดสังเกตว่าตัวอย่างโค้ดด้านล่างจะทำงานทั้งหมดในตัวแฮนเดิลการคลิก แทนที่จะแยกการดำเนินการฐานข้อมูลในบริบทต่างๆ
fun onSetSleepQuality(quality: Int) {
uiScope.launch {
// IO is a thread pool for running operations that access the disk, such as
// our Room database.
withContext(Dispatchers.IO) {
val tonight = database.get(sleepNightKey) ?: return@withContext
tonight.sleepQuality = quality
database.update(tonight)
}
// Setting this state variable to true will alert the observer and trigger navigation.
_navigateToSleepTracker.value = true
}
}
- ในแพ็กเกจ
sleepquality
ให้สร้างหรือเปิดSleepQualityViewModelFactory.kt
แล้วเพิ่มคลาสSleepQualityViewModelFactory
ดังที่แสดงด้านล่าง คลาสนี้ใช้โค้ดบอยเลอร์เพลตเวอร์ชันเดียวกับที่คุณเคยเห็น ตรวจสอบโค้ดก่อนดำเนินการต่อ
class SleepQualityViewModelFactory(
private val sleepNightKey: Long,
private val dataSource: SleepDatabaseDao) : ViewModelProvider.Factory {
@Suppress("unchecked_cast")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(SleepQualityViewModel::class.java)) {
return SleepQualityViewModel(sleepNightKey, dataSource) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
ขั้นตอนที่ 2: อัปเดต SleepQualityFragment
- เปิด
SleepQualityFragment.kt
- ใน
onCreateView()
หลังจากได้รับapplication
แล้ว คุณจะต้องรับarguments
ที่มาพร้อมกับการนำทาง อาร์กิวเมนต์เหล่านี้อยู่ในSleepQualityFragmentArgs
คุณต้องแยกไฟล์เหล่านั้นออกจากแพ็กเกจ
val arguments = SleepQualityFragmentArgs.fromBundle(arguments!!)
- จากนั้นรับ
dataSource
val dataSource = SleepDatabase.getInstance(application).sleepDatabaseDao
- สร้าง Factory โดยส่ง
dataSource
และsleepNightKey
val viewModelFactory = SleepQualityViewModelFactory(arguments.sleepNightKey, dataSource)
- รับ
ViewModel
การอ้างอิง
val sleepQualityViewModel =
ViewModelProviders.of(
this, viewModelFactory).get(SleepQualityViewModel::class.java)
- เพิ่ม
ViewModel
ไปยังออบเจ็กต์การเชื่อมโยง (หากเห็นข้อผิดพลาดเกี่ยวกับออบเจ็กต์การเชื่อมโยง ให้ข้ามไปก่อน)
binding.sleepQualityViewModel = sleepQualityViewModel
- เพิ่มผู้สังเกตการณ์ เมื่อมีข้อความแจ้ง ให้นำเข้า
androidx.lifecycle.Observer
sleepQualityViewModel.navigateToSleepTracker.observe(this, Observer {
if (it == true) { // Observed state is true.
this.findNavController().navigate(
SleepQualityFragmentDirections.actionSleepQualityFragmentToSleepTrackerFragment())
sleepQualityViewModel.doneNavigating()
}
})
ขั้นตอนที่ 3: อัปเดตไฟล์เลย์เอาต์และเรียกใช้แอป
- เปิดไฟล์เลย์เอาต์
fragment_sleep_quality.xml
ในบล็อก<data>
ให้เพิ่มตัวแปรสำหรับSleepQualityViewModel
<data>
<variable
name="sleepQualityViewModel"
type="com.example.android.trackmysleepquality.sleepquality.SleepQualityViewModel" />
</data>
- สำหรับรูปภาพคุณภาพการนอนหลับทั้ง 6 รูป ให้เพิ่มตัวแฮนเดิลการคลิกเหมือนกับตัวแฮนเดิลด้านล่าง จับคู่คะแนนคุณภาพกับรูปภาพ
android:onClick="@{() -> sleepQualityViewModel.onSetSleepQuality(5)}"
- ล้างและสร้างโปรเจ็กต์ใหม่ ซึ่งจะช่วยแก้ไขข้อผิดพลาดเกี่ยวกับออบเจ็กต์การเชื่อมโยง ไม่เช่นนั้น ให้ล้างแคช (File > Invalidate Caches / Restart) แล้วสร้างแอปใหม่
ยินดีด้วย คุณเพิ่งสร้างแอปฐานข้อมูล Room
ที่สมบูรณ์โดยใช้โครูทีน
ตอนนี้แอปของคุณทำงานได้ดีแล้ว ผู้ใช้สามารถแตะเริ่มและหยุดได้หลายครั้งตามต้องการ เมื่อผู้ใช้แตะหยุด ผู้ใช้จะป้อนคุณภาพการนอนหลับได้ เมื่อผู้ใช้แตะล้าง ระบบจะล้างข้อมูลทั้งหมดโดยอัตโนมัติในเบื้องหลัง อย่างไรก็ตาม ปุ่มทั้งหมดจะเปิดใช้และคลิกได้เสมอ ซึ่งจะไม่ทำให้แอปหยุดทำงาน แต่จะอนุญาตให้ผู้ใช้สร้างการนอนหลับที่ไม่สมบูรณ์ได้
ในงานสุดท้ายนี้ คุณจะได้เรียนรู้วิธีใช้แผนที่การเปลี่ยนรูปแบบเพื่อจัดการระดับการมองเห็นปุ่ม เพื่อให้ผู้ใช้เลือกตัวเลือกที่ถูกต้องได้เท่านั้น คุณสามารถใช้วิธีที่คล้ายกันเพื่อแสดงข้อความที่เป็นมิตรหลังจากล้างข้อมูลทั้งหมดแล้ว
ขั้นตอนที่ 1: อัปเดตสถานะปุ่ม
แนวคิดคือการตั้งค่าสถานะปุ่มเพื่อให้ในตอนแรกมีเพียงปุ่มเริ่มเท่านั้นที่เปิดใช้ ซึ่งหมายความว่าปุ่มนี้คลิกได้
หลังจากที่ผู้ใช้แตะเริ่มแล้ว ปุ่มหยุดจะเปิดใช้ได้ แต่ปุ่มเริ่มจะใช้ไม่ได้ ปุ่มล้างจะเปิดใช้เมื่อมีข้อมูลในฐานข้อมูลเท่านั้น
- เปิดไฟล์เลย์เอาต์
fragment_sleep_tracker.xml
- เพิ่มพร็อพเพอร์ตี้
android:enabled
ลงในแต่ละปุ่ม พร็อพเพอร์ตี้android:enabled
เป็นค่าบูลีนที่ระบุว่าปุ่มเปิดใช้หรือไม่ (แตะปุ่มที่เปิดใช้ได้ แต่แตะปุ่มที่ปิดใช้ไม่ได้) กำหนดค่าพร็อพเพอร์ตี้เป็นค่าของตัวแปรสถานะที่คุณจะกำหนดในอีกสักครู่
start_button
:
android:enabled="@{sleepTrackerViewModel.startButtonVisible}"
stop_button
:
android:enabled="@{sleepTrackerViewModel.stopButtonVisible}"
clear_button
:
android:enabled="@{sleepTrackerViewModel.clearButtonVisible}"
- เปิด
SleepTrackerViewModel
แล้วสร้างตัวแปรที่สอดคล้องกัน 3 รายการ กำหนดการเปลี่ยนรูปแบบที่ทดสอบตัวแปรแต่ละรายการ
- ปุ่มเริ่มควรเปิดใช้เมื่อ
tonight
เป็นnull
- ควรเปิดใช้ปุ่มหยุดเมื่อ
tonight
ไม่ใช่null
- ปุ่มล้างควรเปิดใช้ก็ต่อเมื่อ
nights
และฐานข้อมูลมีคืนที่นอนหลับ
val startButtonVisible = Transformations.map(tonight) {
it == null
}
val stopButtonVisible = Transformations.map(tonight) {
it != null
}
val clearButtonVisible = Transformations.map(nights) {
it?.isNotEmpty()
}
- เรียกใช้แอปและทดลองใช้ปุ่มต่างๆ
ขั้นตอนที่ 2: ใช้แถบแสดงข้อความเพื่อแจ้งให้ผู้ใช้ทราบ
หลังจากผู้ใช้ล้างฐานข้อมูลแล้ว ให้แสดงการยืนยันแก่ผู้ใช้โดยใช้วิดเจ็ต Snackbar
แถบแสดงข้อความจะให้คำอธิบายสั้นๆ เกี่ยวกับการดำเนินการผ่านข้อความที่ด้านล่างของหน้าจอ แถบแสดงข้อความจะหายไปหลังจากหมดเวลา หลังจากที่ผู้ใช้โต้ตอบที่อื่นบนหน้าจอ หรือหลังจากที่ผู้ใช้ปัดแถบแสดงข้อความออกจากหน้าจอ
การแสดงแถบแสดงข้อความสั้นๆ เป็นงาน UI และควรเกิดขึ้นใน Fragment การตัดสินใจว่าจะแสดงแถบแสดงข้อความหรือไม่จะเกิดขึ้นใน ViewModel
หากต้องการตั้งค่าและทริกเกอร์แถบแสดงข้อความเมื่อล้างข้อมูล คุณสามารถใช้เทคนิคเดียวกับการทริกเกอร์การนำทางได้
- สร้างเหตุการณ์ที่แคปซูลใน
SleepTrackerViewModel
private var _showSnackbarEvent = MutableLiveData<Boolean>()
val showSnackBarEvent: LiveData<Boolean>
get() = _showSnackbarEvent
- จากนั้นให้ใช้
doneShowingSnackbar()
fun doneShowingSnackbar() {
_showSnackbarEvent.value = false
}
- ใน
SleepTrackerFragment
ในonCreateView()
ให้เพิ่มผู้สังเกตการณ์
sleepTrackerViewModel.showSnackBarEvent.observe(this, Observer { })
- ภายในบล็อก Observer ให้แสดง Snackbar และรีเซ็ตเหตุการณ์ทันที
if (it == true) { // Observed state is true.
Snackbar.make(
activity!!.findViewById(android.R.id.content),
getString(R.string.cleared_message),
Snackbar.LENGTH_SHORT // How long to display the message.
).show()
sleepTrackerViewModel.doneShowingSnackbar()
}
- ใน
SleepTrackerViewModel
ให้ทริกเกอร์เหตุการณ์ในเมธอดonClear()
โดยกำหนดมูลค่าเหตุการณ์เป็นtrue
ภายในบล็อกlaunch
ดังนี้
_showSnackbarEvent.value = true
- สร้างและเรียกใช้แอป
โปรเจ็กต์ Android Studio: TrackMySleepQualityFinal
การติดตั้งใช้งานการติดตามคุณภาพการนอนหลับในแอปนี้ก็เหมือนกับการเล่นเพลงที่คุ้นเคยในคีย์ใหม่ แม้ว่ารายละเอียดจะเปลี่ยนแปลงไป แต่รูปแบบพื้นฐานของสิ่งที่คุณทำใน Codelab ก่อนหน้าในบทเรียนนี้จะยังคงเหมือนเดิม การตระหนักถึงรูปแบบเหล่านี้จะช่วยให้การเขียนโค้ดเร็วขึ้นมาก เนื่องจากคุณสามารถนำโค้ดจากแอปที่มีอยู่มาใช้ซ้ำได้ รูปแบบบางส่วนที่ใช้ในหลักสูตรนี้จนถึงตอนนี้มีดังนี้
- สร้าง
ViewModel
และViewModelFactory
แล้วตั้งค่าแหล่งข้อมูล - ทริกเกอร์การนำทาง หากต้องการแยกความกังวล ให้วางตัวแฮนเดิลการคลิกใน ViewModel และการนำทางใน Fragment
- ใช้การห่อหุ้มกับ
LiveData
เพื่อติดตามและตอบสนองต่อการเปลี่ยนแปลงสถานะ - ใช้การเปลี่ยนรูปแบบกับ
LiveData
- สร้างฐานข้อมูลแบบเดี่ยว
- ตั้งค่าโครูทีนสำหรับการดำเนินการฐานข้อมูล
การทริกเกอร์การนำทาง
คุณกำหนดเส้นทางการนำทางที่เป็นไปได้ระหว่าง Fragment ในไฟล์การนำทาง การเรียกใช้การนำทางจาก Fragment หนึ่งไปยัง Fragment ถัดไปทำได้หลายวิธี ซึ่งได้แก่
- กำหนด
onClick
ตัวแฮนเดิลเพื่อทริกเกอร์การนำทางไปยัง Fragment ปลายทาง - หรือหากต้องการเปิดใช้การนำทางจาก Fragment หนึ่งไปยัง Fragment ถัดไป ให้ทำดังนี้
- กําหนดค่า
LiveData
เพื่อบันทึกว่าควรมีการนําทางหรือไม่ - แนบ Observer กับค่า
LiveData
นั้น - จากนั้นโค้ดจะเปลี่ยนค่าดังกล่าวเมื่อใดก็ตามที่ต้องทริกเกอร์การนำทางหรือการนำทางเสร็จสมบูรณ์
การตั้งค่าแอตทริบิวต์ android:enabled
- แอตทริบิวต์
android:enabled
มีการกำหนดไว้ในTextView
และคลาสย่อยทั้งหมดจะรับค่าแอตทริบิวต์นี้ รวมถึงButton
- แอตทริบิวต์
android:enabled
จะกำหนดว่าจะเปิดใช้View
หรือไม่ ความหมายของ "เปิดใช้" จะแตกต่างกันไปตามคลาสย่อย เช่นEditText
ที่ไม่ได้เปิดใช้จะป้องกันไม่ให้ผู้ใช้แก้ไขข้อความที่อยู่ในนั้น และButton
ที่ไม่ได้เปิดใช้จะป้องกันไม่ให้ผู้ใช้แตะปุ่ม - แอตทริบิวต์
enabled
ไม่เหมือนกับแอตทริบิวต์visibility
- คุณสามารถใช้แผนที่การเปลี่ยนรูปแบบเพื่อกำหนดค่าของแอตทริบิวต์
enabled
ของปุ่มตามสถานะของออบเจ็กต์หรือตัวแปรอื่น
ประเด็นอื่นๆ ที่ครอบคลุมใน Codelab นี้มีดังนี้
- หากต้องการทริกเกอร์การแจ้งเตือนให้ผู้ใช้ คุณสามารถใช้วิธีเดียวกับที่ใช้ทริกเกอร์การนำทาง
- คุณใช้
Snackbar
เพื่อแจ้งเตือนผู้ใช้ได้
หลักสูตร Udacity:
เอกสารประกอบสำหรับนักพัฒนาแอป Android
ส่วนนี้แสดงรายการการบ้านที่เป็นไปได้สำหรับนักเรียน/นักศึกษาที่กำลังทำ Codelab นี้เป็นส่วนหนึ่งของหลักสูตรที่สอนโดยผู้สอน ผู้สอนมีหน้าที่ดำเนินการต่อไปนี้
- มอบหมายการบ้านหากจำเป็น
- สื่อสารกับนักเรียนเกี่ยวกับวิธีส่งงานที่ได้รับมอบหมาย
- ให้คะแนนงานการบ้าน
ผู้สอนสามารถใช้คำแนะนำเหล่านี้ได้มากน้อยตามที่ต้องการ และควรมีอิสระในการมอบหมายการบ้านอื่นๆ ที่เห็นว่าเหมาะสม
หากคุณกำลังทำ Codelab นี้ด้วยตนเอง โปรดใช้แบบฝึกหัดเหล่านี้เพื่อทดสอบความรู้ของคุณ
ตอบคำถามต่อไปนี้
คำถามที่ 1
วิธีหนึ่งในการเปิดใช้แอปเพื่อทริกเกอร์การนำทางจาก Fragment หนึ่งไปยังอีก Fragment คือการใช้ค่า LiveData
เพื่อระบุว่าจะทริกเกอร์การนำทางหรือไม่
ขั้นตอนในการใช้ค่า LiveData
ที่เรียกว่า gotoBlueFragment
เพื่อทริกเกอร์การนำทางจาก Fragment สีแดงไปยัง Fragment สีน้ำเงินมีอะไรบ้าง โดยเลือกได้มากกว่า 1 ข้อ
- ใน
ViewModel
ให้กำหนดค่าLiveData
เป็นgotoBlueFragment
- ใน
RedFragment
ให้สังเกตค่าgotoBlueFragment
ใช้โค้ดobserve{}
เพื่อไปยังBlueFragment
เมื่อเหมาะสม จากนั้นรีเซ็ตค่าของgotoBlueFragment
เพื่อระบุว่าการนำทางเสร็จสมบูรณ์แล้ว - ตรวจสอบว่าโค้ดตั้งค่าตัวแปร
gotoBlueFragment
เป็นค่าที่ทริกเกอร์การนำทางทุกครั้งที่แอปต้องเปลี่ยนจากRedFragment
ไปยังBlueFragment
- ตรวจสอบว่าโค้ดของคุณกําหนดแฮนเดิล
onClick
สําหรับView
ที่ผู้ใช้คลิกเพื่อไปยังBlueFragment
ซึ่งแฮนเดิลonClick
จะสังเกตค่าgoToBlueFragment
คำถามที่ 2
คุณเปลี่ยนได้ว่าจะเปิดใช้ (คลิกได้) หรือไม่เปิดใช้ Button
โดยใช้ LiveData
คุณจะตรวจสอบว่าแอปเปลี่ยนปุ่ม UpdateNumber
เพื่อให้มีลักษณะดังนี้ได้อย่างไร
- ปุ่มจะเปิดใช้หาก
myNumber
มีค่ามากกว่า 5 - ปุ่มจะปิดใช้อยู่หาก
myNumber
เท่ากับหรือน้อยกว่า 5
สมมติว่าเลย์เอาต์ที่มีปุ่ม UpdateNumber
มีตัวแปร <data>
สำหรับ NumbersViewModel
ดังที่แสดงที่นี่
<data> <variable name="NumbersViewModel" type="com.example.android.numbersapp.NumbersViewModel" /> </data>
สมมติว่ารหัสของปุ่มในไฟล์เลย์เอาต์เป็นดังนี้
android:id="@+id/update_number_button"
สิ่งที่ต้องทำเพิ่มเติม เลือกได้มากกว่า 1 ข้อ
- ในคลาส
NumbersViewModel
ให้กำหนดตัวแปรLiveData
,myNumber
ซึ่งแสดงถึงตัวเลข นอกจากนี้ ให้กำหนดตัวแปรที่มีค่าที่ตั้งค่าโดยการเรียกTransform.map()
ในตัวแปรmyNumber
ซึ่งจะแสดงผลบูลีนที่ระบุว่าตัวเลขนั้นมากกว่า 5 หรือไม่
กล่าวคือ ในViewModel
ให้เพิ่มโค้ดต่อไปนี้
val myNumber: LiveData<Int>
val enableUpdateNumberButton = Transformations.map(myNumber) {
myNumber > 5
}
- ในเลย์เอาต์ XML ให้ตั้งค่าแอตทริบิวต์
android:enabled
ของupdate_number_button button
เป็นNumberViewModel.enableUpdateNumbersButton
android:enabled="@{NumbersViewModel.enableUpdateNumberButton}"
- ใน
Fragment
ที่ใช้คลาสNumbersViewModel
ให้เพิ่ม Observer ลงในแอตทริบิวต์enabled
ของปุ่ม
กล่าวคือ ในFragment
ให้เพิ่มโค้ดต่อไปนี้
// Observer for the enabled attribute
viewModel.enabled.observe(this, Observer<Boolean> { isEnabled ->
myNumber > 5
})
- ในไฟล์เลย์เอาต์ ให้ตั้งค่าแอตทริบิวต์
android:enabled
ของupdate_number_button button
เป็น"Observable"
ไปที่บทเรียนถัดไป:
ดูลิงก์ไปยัง Codelab อื่นๆ ในหลักสูตรนี้ได้ที่หน้า Landing Page ของ Codelab หลักพื้นฐานของ Android Kotlin