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 = oldNightSleepTrackerFragmentต้องสังเกต _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