Codelab นี้เป็นส่วนหนึ่งของหลักสูตรพื้นฐานเกี่ยวกับ Kotlin ใน Android คุณจะได้รับประโยชน์สูงสุดจากหลักสูตรนี้ หากทํางานผ่าน Codelab ตามลําดับ Codelab ของหลักสูตรทั้งหมดจะแสดงอยู่ในหน้า Landing Page ของ Codelab ของ Android Kotlin Fundamentals
ข้อมูลเบื้องต้น
Codelab นี้จะสรุปวิธีใช้ ViewModel
และ Fragment ร่วมกันเพื่อนําการนําทาง โปรดทราบว่าเป้าหมายคือการวางตรรกะเมื่อเพื่อเข้าสู่ ViewModel
แต่กําหนดเส้นทางในส่วนย่อยและไฟล์การนําทาง หากต้องการบรรลุเป้าหมายนี้ คุณจะต้องใช้โมเดลการดู ส่วนย่อย LiveData
และการสังเกตการณ์
Codelab สรุปโดยการแสดงวิธีติดตามสถานะปุ่มที่ชาญฉลาดโดยใช้โค้ดจํานวนน้อย เพื่อให้ปุ่มแต่ละปุ่มเปิดใช้งานและคลิกได้เมื่อมีความเหมาะสมที่จะให้ผู้ใช้แตะปุ่มดังกล่าวเท่านั้น
สิ่งที่ควรทราบอยู่แล้ว
คุณควรทําความคุ้นเคยกับสิ่งต่อไปนี้
- การสร้างอินเทอร์เฟซผู้ใช้ (UI) พื้นฐานโดยใช้กิจกรรม ส่วนย่อย และข้อมูลพร็อพเพอร์ตี้
- ไปยังส่วนต่างๆ ระหว่างส่วนย่อยและใช้
safeArgs
เพื่อส่งข้อมูลระหว่างส่วนย่อย - ดูโมเดล ดูโรงงานของโมเดล การเปลี่ยนรูปแบบ และ
LiveData
และการสังเกตการณ์ - วิธีสร้างฐานข้อมูล
Room
สร้างออบเจ็กต์การเข้าถึงข้อมูล (DAO) และกําหนดเอนทิตี - วิธีใช้โครูทีนสําหรับการโต้ตอบกับฐานข้อมูลและงานอื่นๆ ที่ใช้เวลานาน
สิ่งที่คุณจะได้เรียนรู้
- วิธีอัปเดตระเบียนคุณภาพการนอนหลับที่มีอยู่ในฐานข้อมูล
- วิธีใช้
LiveData
เพื่อติดตามสถานะของปุ่ม - วิธีแสดงสแน็กบาร์เพื่อตอบสนองต่อกิจกรรม
สิ่งที่คุณจะทํา
- ขยายแอป TrackMySleepคุณภาพ เพื่อรวบรวมคะแนนคุณภาพ เพิ่มคะแนนในฐานข้อมูล และแสดงผลลัพธ์
- ใช้
LiveData
เพื่อเรียกใช้การแสดง Snackbar - ใช้
LiveData
เพื่อเปิดใช้และปิดใช้ปุ่ม
ใน Codelab นี้ คุณสร้างการบันทึกคุณภาพการนอนหลับและ UI สุดท้ายของแอป TrackMySleepคุณภาพ
แอปมีหน้าจอ 2 หน้าจอ ซึ่งแสดงผลด้วยส่วนย่อยตามที่แสดงในภาพด้านล่าง
หน้าจอแรกที่แสดงทางด้านซ้ายมีปุ่มให้เริ่มและหยุดการติดตาม หน้าจอแสดงข้อมูลการนอนหลับของผู้ใช้ทั้งหมด ปุ่มล้างจะลบข้อมูลทั้งหมดที่แอปรวบรวมให้กับผู้ใช้อย่างถาวร
หน้าจอที่ 2 ที่แสดงทางด้านขวาคือการเลือกคะแนนคุณภาพการนอนหลับ ในแอป ตัวเลขจะแสดงเป็นตัวเลข แอปจะแสดงทั้งไอคอนใบหน้าและตัวเลขที่เทียบเท่าเพื่อวัตถุประสงค์ในการพัฒนา
โฟลว์ผู้ใช้มีดังนี้
- ผู้ใช้เปิดแอปและนําเสนอด้วยหน้าจอติดตามการนอนหลับ
- ผู้ใช้แตะปุ่มเริ่ม ซึ่งจะบันทึกเวลาเริ่มต้นและแสดง ปุ่มเริ่มต้นปิดใช้อยู่ และปุ่มหยุดเปิดใช้งานอยู่
- ผู้ใช้แตะปุ่มหยุด ซึ่งจะบันทึกเวลาสิ้นสุดและเปิดหน้าจอคุณภาพการนอนหลับ
- ผู้ใช้เลือกไอคอนคุณภาพการนอนหลับ หน้าจอจะปิดลงและหน้าจอการติดตามจะแสดงเวลานอนและคุณภาพการนอนหลับ ปุ่มหยุดปิดใช้อยู่และปุ่มเริ่มต้นจะเปิดใช้อยู่ แอปพร้อมใช้งานสําหรับอีกคืนหนึ่ง
- ปุ่มล้างจะเปิดใช้เมื่อใดก็ตามที่มีข้อมูลในฐานข้อมูล เมื่อผู้ใช้แตะปุ่มล้างระบบจะลบข้อมูลทั้งหมดของผู้ใช้โดยไม่ออกคําสั่ง เพราะไม่มี "คุณแน่ใจหรือเรียกว่า CPD ข้อความ
แอปนี้ใช้สถาปัตยกรรมแบบง่ายดังที่แสดงด้านล่างในบริบทของสถาปัตยกรรมแบบเต็ม แอปใช้คอมโพเนนต์ต่อไปนี้เท่านั้น
- ตัวควบคุม UI
- ดูโมเดลและ
LiveData
- ฐานข้อมูลห้องแชท
Codelab นี้จะถือว่าคุณทราบวิธีใช้การนําทางโดยใช้ Fragment และไฟล์การนําทางแล้ว เรามีดีลดีๆ ให้คุณเพื่อบันทึกดีลนี้
ขั้นตอนที่ 1: ตรวจสอบโค้ด
- ในการเริ่มต้นใช้งาน ให้ดําเนินการต่อโดยใช้โค้ดของคุณเองจากส่วนท้ายของ Codelab ครั้งล่าสุด หรือดาวน์โหลดโค้ดเริ่มต้น
- ตรวจสอบ
SleepQualityFragment
ในโค้ดเริ่มต้น คลาสนี้จะขยายเลย์เอาต์ รับแอปพลิเคชัน และส่งคืนbinding.root
- เปิด navigation.xml ในตัวแก้ไขดีไซน์ คุณเห็นเส้นทางการนําทางจาก
SleepTrackerFragment
ไปSleepQualityFragment
และย้อนกลับอีกครั้งจากSleepQualityFragment
ไปSleepTrackerFragment
- ตรวจสอบโค้ดสําหรับ navigation.xml โดยเฉพาะอย่างยิ่ง ให้มองหา
<argument>
ที่ชื่อsleepNightKey
เมื่อผู้ใช้เปลี่ยนจากSleepTrackerFragment
ไปยังSleepQualityFragment,
แอปจะส่งsleepNightKey
ไปยังSleepQualityFragment
สําหรับคืนที่ต้องอัปเดต
ขั้นตอนที่ 2: เพิ่มการนําทางสําหรับการติดตามคุณภาพการนอนหลับ
กราฟการนําทางมีเส้นทางจาก SleepTrackerFragment
ไป SleepQualityFragment
แล้ว และกลับไปอีกครั้ง อย่างไรก็ตาม เครื่องจัดการการคลิกที่ใช้การนําทางจากส่วนย่อยหนึ่งไปยังหน้าถัดไปยังไม่ได้เขียนโค้ด คุณเพิ่มรหัสดังกล่าวได้ใน ViewModel
แล้ว
ในเครื่องจัดการคลิก คุณตั้งค่า LiveData
ที่จะเปลี่ยนแปลงเมื่อคุณต้องการให้แอปนําทางไปยังจุดหมายอื่น ส่วนย่อยสังเกต LiveData
นี้ เมื่อข้อมูลมีการเปลี่ยนแปลง ส่วนย่อยจะนําทางไปยังปลายทางและบอกโมเดลมุมมองว่าเสร็จสิ้นแล้ว ซึ่งจะรีเซ็ตตัวแปรของสถานะ
- เปิด
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 {
})
- ภายในบล็อกผู้สังเกตการณ์ ให้นําทางและผ่านรหัสในคืนปัจจุบัน แล้วเรียก
doneNavigating()
หากการนําเข้าของคุณไม่ชัดเจน ให้นําเข้าandroidx.navigation.fragment.findNavController
night ->
night?.let {
this.findNavController().navigate(
SleepTrackerFragmentDirections
.actionSleepTrackerFragmentToSleepQualityFragment(night.nightId))
sleepTrackerViewModel.doneNavigating()
}
- สร้างและเรียกใช้แอป แตะเริ่ม แล้วแตะหยุด ซึ่งจะนําคุณไปยังหน้าจอ
SleepQualityFragment
ใช้ปุ่มย้อนกลับเพื่อย้อนกลับ
ในงานนี้ คุณจะบันทึกคุณภาพการนอนหลับและกลับไปยังส่วนการติดตามการนอนหลับ จอแสดงผลควรอัปเดตโดยอัตโนมัติเพื่อแสดงค่าที่อัปเดตต่อผู้ใช้ คุณต้องสร้าง ViewModel
และ ViewModelFactory
และต้องอัปเดต SleepQualityFragment
ขั้นตอนที่ 1: สร้าง Viewmodel และ ViewModelFactory
- ในแพ็กเกจ
sleepquality
ให้สร้างหรือเปิด SleepคุณภาพViewModel.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
}
- สร้างเครื่องจัดการแบบคลิกครั้งเดียว
onSetSleepQuality()
เพื่อใช้รูปภาพที่มีคุณภาพในการนอนหลับทั้งหมด
ใช้รูปแบบ Coroutine เดียวกันกับ Codelab ก่อนหน้า ดังนี้
- เปิดตัว Coroutine ใน
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
ดังที่แสดงด้านล่าง ชั้นเรียนนี้ใช้โค้ด Boilerplate แบบเดียวกับที่คุณเคยเห็นมาก่อน ตรวจสอบโค้ดก่อนดําเนินการต่อ
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.kt
- ใน
onCreateView()
หลังจากได้รับapplication
คุณต้องได้รับarguments
ที่มาพร้อมกับการนําทาง อาร์กิวเมนต์เหล่านี้อยู่ในSleepQualityFragmentArgs
คุณต้องแตกไฟล์ออกจากแพ็กเกจ
val arguments = SleepQualityFragmentArgs.fromBundle(arguments!!)
- ถัดไป ให้ไปที่
dataSource
val dataSource = SleepDatabase.getInstance(application).sleepDatabaseDao
- สร้างโรงงานโดยผ่านใน
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
เพิ่มตัวแปรสําหรับSleepQualityViewModel
ในบล็อก<data>
<data>
<variable
name="sleepQualityViewModel"
type="com.example.android.trackmysleepquality.sleepquality.SleepQualityViewModel" />
</data>
- สําหรับรูปภาพที่มีคุณภาพในการนอนหลับทั้ง 6 ภาพ ให้เพิ่มเครื่องจัดการการคลิกเหมือนตัวอย่างด้านล่าง จับคู่คะแนนคุณภาพกับรูปภาพ
android:onClick="@{() -> sleepQualityViewModel.onSetSleepQuality(5)}"
- ทําความสะอาดและสร้างโปรเจ็กต์อีกครั้ง การดําเนินการนี้จะแก้ไขข้อผิดพลาดที่มีออบเจ็กต์การเชื่อมโยงได้ หรือล้างแคช (File >Invalidate Caches / Restart) แล้วสร้างแอปอีกครั้ง
ยินดีด้วย คุณเพิ่งสร้างแอปฐานข้อมูล Room
ที่สมบูรณ์โดยใช้ Coroutine
ตอนนี้แอปของคุณก็ทํางานดีแล้ว ผู้ใช้แตะเริ่มและหยุดกี่ครั้งก็ได้ตามที่ต้องการ เมื่อแตะหยุด ผู้ใช้จะเข้าสู่คุณภาพการนอนหลับได้ เมื่อผู้ใช้แตะล้าง ระบบจะล้างข้อมูลทั้งหมดในเบื้องหลังอย่างเงียบๆ อย่างไรก็ตาม ปุ่มทั้งหมดจะเปิดใช้และคลิกได้ทุกเมื่อ ซึ่งไม่ทําให้แอปเสียหาย แต่ผู้ใช้สามารถสร้างช่วงการนอนหลับที่ไม่สมบูรณ์ได้
ในงานสุดท้ายนี้ คุณจะได้เรียนรู้วิธีใช้แผนที่การเปลี่ยนแปลงเพื่อจัดการระดับการมองเห็นปุ่มเพื่อให้ผู้ใช้เลือกได้อย่างเหมาะสมเท่านั้น คุณสามารถใช้วิธีการที่คล้ายกันนี้เพื่อแสดงข้อความที่เป็นมิตรหลังจากล้างข้อมูลทั้งหมดเรียบร้อยแล้ว
ขั้นตอนที่ 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
สแน็คบาร์จะให้ความคิดเห็นสั้นๆ เกี่ยวกับการดําเนินการผ่านข้อความที่ด้านล่างของหน้าจอ สแน็กบาร์จะหายไปหลังจากหมดเวลา หรือหลังจากผู้ใช้สแน็กบาร์เลื่อนหน้าจอออกจากหน้าจอ
การแสดง Snackbar เป็นงานใน UI ซึ่งจะเกิดขึ้นใน Fragment การตัดสินใจแสดง Snackbar จะเกิดขึ้นใน ViewModel
หากต้องการตั้งค่าและเรียก Snackbar เมื่อล้างข้อมูลแล้ว คุณจะใช้เทคนิคเดียวกับการทริกเกอร์การนําทางได้
- สร้างเหตุการณ์ที่ปกปิดใน
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 { })
- แสดงสแน็คบาร์และรีเซ็ตเหตุการณ์ภายในบล็อกผู้สังเกตการณ์
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: TrackMySleepคุณภาพFinal
การใช้งานการติดตามคุณภาพการนอนหลับในแอปนี้ก็เหมือนกับการเล่นเพลงที่คุ้นเคยในคีย์ใหม่ แม้ว่ารายละเอียดจะเปลี่ยนไป แต่รูปแบบพื้นฐานของสิ่งที่คุณทําใน Codelab ก่อนหน้านี้ในบทเรียนนี้จะยังคงเหมือนเดิม การระวังรูปแบบเหล่านี้จะทําให้การเขียนโค้ดเร็วขึ้นมาก เนื่องจากคุณนําโค้ดจากแอปที่มีอยู่มาใช้ซ้ําได้ ตัวอย่างรูปแบบที่ใช้ในหลักสูตรนี้มีดังนี้
- สร้าง
ViewModel
และViewModelFactory
และตั้งค่าแหล่งข้อมูล - การนําทางทริกเกอร์ หากต้องการแยกข้อกังวลออกมา ให้ใส่เครื่องจัดการการคลิกในโมเดลมุมมองและการนําทางในส่วนย่อย
- ใช้ข้อมูลสรุปกับ
LiveData
เพื่อติดตามและตอบสนองต่อการเปลี่ยนแปลงสถานะ - ใช้การเปลี่ยนรูปแบบกับ
LiveData
- สร้างฐานข้อมูลรายการเดียว
- ตั้งค่า Coroutine สําหรับการทํางานของฐานข้อมูล
การเริ่มการนําทาง
คุณกําหนดเส้นทางที่เป็นไปได้สําหรับการนําทางระหว่างส่วนย่อยในไฟล์การนําทาง เรียกใช้การนําทางจากส่วนย่อยหนึ่งไปยังอีกส่วนได้หลายวิธี ซึ่งได้แก่
- กําหนดเครื่องจัดการ
onClick
เพื่อทริกเกอร์การนําทางไปยังส่วนย่อยปลายทาง - หรือหากต้องการเปิดใช้การนําทางจากส่วนย่อยหนึ่งไปยังหน้าถัดไป
- กําหนดค่า
LiveData
เพื่อบันทึกว่าควรมีการนําทางหรือไม่ - แนบตัวสังเกตกับค่า
LiveData
นั้น - โค้ดจะเปลี่ยนค่านั้นเมื่อใดก็ตามที่จําเป็นต้องทริกเกอร์การนําทางหรือเสร็จสิ้น
การตั้งค่าแอตทริบิวต์ android:enabled
- แอตทริบิวต์
android:enabled
กําหนดไว้ในTextView
และรับช่วงมาจากคลาสย่อยทั้งหมด รวมถึงButton
- แอตทริบิวต์
android:enabled
เลือกว่าจะเปิดใช้View
หรือไม่ ความหมายของ "enabled" จะแตกต่างกันไปตามคลาสย่อย ตัวอย่างเช่นEditText
ที่เปิดใช้ไม่ได้จะป้องกันไม่ให้ผู้ใช้แก้ไขข้อความที่มีอยู่ และButton
ที่เปิดใช้ไม่ได้จะทําให้ผู้ใช้แตะปุ่มไม่ได้ - แอตทริบิวต์
enabled
ไม่เหมือนกับแอตทริบิวต์visibility
- คุณใช้การแมปการเปลี่ยนรูปแบบเพื่อตั้งค่าแอตทริบิวต์
enabled
ของปุ่มตามสถานะของออบเจ็กต์หรือตัวแปรอื่นได้
จุดอื่นๆ ที่ครอบคลุมใน Codelab นี้
- หากต้องการทริกเกอร์การแจ้งเตือนให้กับผู้ใช้ ให้ใช้เทคนิคเดียวกับที่ใช้เรียกใช้การนําทาง
- คุณสามารถใช้
Snackbar
เพื่อแจ้งผู้ใช้
หลักสูตร Udacity:
เอกสารประกอบสําหรับนักพัฒนาซอฟต์แวร์ Android
ส่วนนี้จะอธิบายการบ้านและรายงานสําหรับนักเรียนที่ทํางานผ่าน Codelab นี้ซึ่งเป็นส่วนหนึ่งของหลักสูตรที่นําโดยผู้สอน สิ่งที่ผู้สอนต้องทํามีดังนี้
- มอบหมายการบ้านหากจําเป็น
- สื่อสารกับนักเรียนเกี่ยวกับวิธีส่งงานทําการบ้าน
- ตัดเกรดการบ้าน
ผู้สอนจะใช้คําแนะนําเหล่านี้เท่าใดก็ได้หรือตามที่ต้องการก็ได้ และสามารถกําหนดให้การบ้านอื่นๆ ที่ตนคิดว่าเหมาะสมได้
หากคุณใช้ Codelab ด้วยตัวเอง ก็ให้ใช้การบ้านเพื่อทดสอบความรู้ของคุณได้
ตอบคําถามเหล่านี้
คำถามที่ 1
วิธีหนึ่งที่จะอนุญาตให้แอปทริกเกอร์การนําทางจากส่วนย่อยหนึ่งไปยังอีกส่วนหนึ่งได้ คือใช้ค่า LiveData
เพื่อระบุว่าจะทริกเกอร์การนําทางหรือไม่
ขั้นตอนการใช้ค่า LiveData
ที่เรียกว่า gotoBlueFragment
เพื่อทริกเกอร์การนําทางจากส่วนย่อยสีแดงไปยังส่วนย่อยสีน้ําเงินมีอะไรบ้าง เลือกได้มากกว่า 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
ให้เพิ่มการสังเกตการณ์ไปยังแอตทริบิวต์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 Fundamentals