Codelab นี้เป็นส่วนหนึ่งของหลักสูตรหลักพื้นฐานของ Android Kotlin คุณจะได้รับประโยชน์สูงสุดจากหลักสูตรนี้หากทำตาม Codelab ตามลำดับ Codelab ของหลักสูตรทั้งหมดแสดงอยู่ในหน้า Landing Page ของ Codelab หลักพื้นฐานของ Android Kotlin
บทนำ
ใน Codelab ก่อนหน้าในบทเรียนนี้ คุณได้ปรับปรุงโค้ดสำหรับแอป GuessTheWord ตอนนี้แอปใช้ViewModelออบเจ็กต์แล้ว ดังนั้นข้อมูลแอปจึงยังคงอยู่แม้จะมีการเปลี่ยนแปลงการกำหนดค่าอุปกรณ์ เช่น การหมุนหน้าจอและการเปลี่ยนแปลงความพร้อมใช้งานของแป้นพิมพ์ นอกจากนี้ คุณยังเพิ่ม LiveData ที่สังเกตได้ด้วย ดังนั้นมุมมองจะได้รับการแจ้งเตือนโดยอัตโนมัติเมื่อข้อมูลที่สังเกตมีการเปลี่ยนแปลง
ในโค้ดแล็บนี้ คุณจะทำงานกับแอป GuessTheWord ต่อไป โดยจะเชื่อมโยงมุมมองกับคลาส ViewModel ในแอปเพื่อให้มุมมองในเลย์เอาต์สื่อสารกับออบเจ็กต์ ViewModel ได้โดยตรง (ก่อนหน้านี้ในแอปของคุณ มุมมองจะสื่อสารกับ ViewModel โดยอ้อมผ่าน Fragment ของแอป) หลังจากผสานรวมการเชื่อมโยงข้อมูลกับออบเจ็กต์ ViewModel แล้ว คุณไม่จำเป็นต้องมีตัวแฮนเดิลการคลิกใน Fragment ของแอปอีกต่อไป จึงนำออกได้
นอกจากนี้ คุณยังเปลี่ยนแอป GuessTheWord ให้ใช้ LiveData เป็นแหล่งข้อมูลการเชื่อมโยงข้อมูลเพื่อแจ้งให้ UI ทราบเกี่ยวกับการเปลี่ยนแปลงข้อมูลได้โดยไม่ต้องใช้วิธีการสังเกตการณ์ LiveData
สิ่งที่คุณควรทราบอยู่แล้ว
- วิธีสร้างแอป Android พื้นฐานใน Kotlin
- วิธีการทำงานของวงจรของกิจกรรมและ Fragment
- วิธีใช้
ViewModelในแอป - วิธีจัดเก็บข้อมูลโดยใช้
LiveDataในViewModel - วิธีเพิ่มเมธอด Observer เพื่อสังเกตการเปลี่ยนแปลงใน
LiveDataข้อมูล
สิ่งที่คุณจะได้เรียนรู้
- วิธีใช้องค์ประกอบของไลบรารีการเชื่อมโยงข้อมูล
- วิธีผสานรวม
ViewModelกับการเชื่อมโยงข้อมูล - วิธีผสานรวม
LiveDataกับการเชื่อมโยงข้อมูล - วิธีใช้การเชื่อมโยง Listener เพื่อแทนที่ Listener การคลิกใน Fragment
- วิธีเพิ่มการจัดรูปแบบสตริงลงในนิพจน์การเชื่อมโยงข้อมูล
สิ่งที่คุณต้องดำเนินการ
- มุมมองในเลย์เอาต์ GuessTheWord จะสื่อสารกับออบเจ็กต์
ViewModelโดยอ้อมโดยใช้ตัวควบคุม UI (Fragment) เพื่อส่งต่อข้อมูล ในโค้ดแล็บนี้ คุณจะเชื่อมโยงมุมมองของแอปกับออบเจ็กต์ViewModelเพื่อให้มุมมองสื่อสารกับออบเจ็กต์ViewModelได้โดยตรง - คุณเปลี่ยนแอปให้ใช้
LiveDataเป็นแหล่งที่มาของการเชื่อมโยงข้อมูล หลังจากทำการเปลี่ยนแปลงนี้แล้ว ออบเจ็กต์LiveDataจะแจ้งให้ UI ทราบเกี่ยวกับการเปลี่ยนแปลงข้อมูล และไม่จำเป็นต้องใช้วิธีการสังเกตการณ์LiveDataอีกต่อไป
ใน Codelab บทที่ 5 คุณจะได้พัฒนาแอป GuessTheWord โดยเริ่มจากโค้ดเริ่มต้น GuessTheWord เป็นเกมสไตล์ใบ้คำสำหรับผู้เล่น 2 คน โดยผู้เล่นจะต้องร่วมมือกันเพื่อให้ได้คะแนนสูงสุดเท่าที่จะเป็นไปได้
ผู้เล่นคนแรกดูคำในแอปและแสดงท่าทางของคำนั้นทีละคำ โดยต้องไม่ให้ผู้เล่นคนที่ 2 เห็นคำ ผู้เล่นคนที่ 2 พยายามทายคำ
หากต้องการเล่นเกม ผู้เล่นคนแรกจะเปิดแอปในอุปกรณ์และเห็นคำ เช่น "กีตาร์" ดังที่แสดงในภาพหน้าจอด้านล่าง
ผู้เล่นคนแรกจะแสดงท่าทางตามคำนั้น โดยระมัดระวังไม่ให้พูดคำนั้นออกมาจริงๆ
- เมื่อผู้เล่นคนที่ 2 ทายคำถูกต้อง ผู้เล่นคนแรกจะกดปุ่มเข้าใจแล้ว ซึ่งจะเพิ่มจำนวนขึ้น 1 และแสดงคำถัดไป
- หากผู้เล่นคนที่ 2 เดาคำไม่ได้ ผู้เล่นคนแรกจะกดปุ่มข้าม ซึ่งจะลดจำนวนลง 1 และข้ามไปยังคำถัดไป
- หากต้องการจบเกม ให้กดปุ่มจบเกม (ฟังก์ชันนี้ไม่ได้อยู่ในโค้ดเริ่มต้นสำหรับโค้ดแล็บแรกในชุด)
ในโค้ดแล็บนี้ คุณจะปรับปรุงแอป GuessTheWord โดยผสานรวมการเชื่อมโยงข้อมูลกับ LiveData ในออบเจ็กต์ ViewModel ซึ่งจะทำให้การสื่อสารระหว่างมุมมองในเลย์เอาต์กับออบเจ็กต์ ViewModel เป็นไปโดยอัตโนมัติ และช่วยให้คุณลดความซับซ้อนของโค้ดได้โดยใช้ LiveData
หน้าจอชื่อ |
หน้าจอเกม |
หน้าจอคะแนน |
ในงานนี้ คุณจะได้ค้นหาและเรียกใช้โค้ดเริ่มต้นสำหรับ Codelab นี้ คุณสามารถใช้แอป GuessTheWord ที่สร้างใน Codelab ก่อนหน้าเป็นโค้ดเริ่มต้น หรือจะดาวน์โหลดแอปเริ่มต้นก็ได้
- (ไม่บังคับ) หากไม่ได้ใช้โค้ดจาก Codelab ก่อนหน้า ให้ดาวน์โหลดโค้ดเริ่มต้นสำหรับ Codelab นี้ คลายซิปรหัสและเปิดโปรเจ็กต์ใน Android Studio
- เรียกใช้แอปและเล่นเกม
- โปรดทราบว่าปุ่มรับทราบจะแสดงคำถัดไปและเพิ่มคะแนนขึ้น 1 คะแนน ส่วนปุ่มข้ามจะแสดงคำถัดไปและลดคะแนนลง 1 คะแนน ปุ่มจบเกมจะสิ้นสุดเกม
- เลื่อนดูคำทั้งหมด แล้วสังเกตว่าแอปจะไปยังหน้าจอคะแนนโดยอัตโนมัติ
ในโค้ดแล็บก่อนหน้านี้ คุณใช้การเชื่อมโยงข้อมูลเป็นวิธีที่ปลอดภัยต่อประเภทในการเข้าถึงมุมมองในแอป GuessTheWord แต่ศักยภาพที่แท้จริงของการเชื่อมโยงข้อมูลคือการทำตามชื่อที่แนะนำ นั่นคือการเชื่อมโยงข้อมูลโดยตรงกับออบเจ็กต์มุมมองในแอป
สถาปัตยกรรมแอปปัจจุบัน
ในแอป มุมมองจะกำหนดไว้ในเลย์เอาต์ XML และข้อมูลสำหรับมุมมองเหล่านั้นจะอยู่ในออบเจ็กต์ ViewModel ระหว่างมุมมองแต่ละมุมมองกับ ViewModel ที่เกี่ยวข้องจะมีตัวควบคุม UI ซึ่งทำหน้าที่เป็นรีเลย์ระหว่างมุมมองเหล่านั้น

เช่น
- ปุ่มรับทราบกำหนดเป็น
Buttonมุมมองในไฟล์เลย์เอาต์game_fragment.xml - เมื่อผู้ใช้แตะปุ่มรับทราบ ตัวตรวจหาการคลิกใน Fragment
GameFragmentจะเรียกตัวตรวจหาการคลิกที่เกี่ยวข้องในGameViewModel - ระบบจะอัปเดตคะแนนใน
GameViewModel
Button และ GameViewModel ไม่ได้สื่อสารกันโดยตรง แต่ต้องใช้เครื่องมือฟังการคลิกที่อยู่ใน GameFragment
ViewModel ที่ส่งไปยัง Data Binding
การสื่อสารโดยตรงระหว่างมุมมองในเลย์เอาต์กับข้อมูลในViewModelออบเจ็กต์จะง่ายกว่าโดยไม่ต้องอาศัยตัวควบคุม UI เป็นตัวกลาง

ออบเจ็กต์ ViewModel จะเก็บข้อมูล UI ทั้งหมดในแอป GuessTheWord การส่งออบเจ็กต์ ViewModel ไปยัง Data Binding จะช่วยให้คุณทำให้การสื่อสารบางอย่างระหว่าง View กับออบเจ็กต์ ViewModel เป็นแบบอัตโนมัติได้
ในงานนี้ คุณจะเชื่อมโยงคลาส GameViewModel และ ScoreViewModel กับเลย์เอาต์ XML ที่เกี่ยวข้อง นอกจากนี้ คุณยังตั้งค่าการเชื่อมโยง Listener เพื่อจัดการเหตุการณ์คลิกได้ด้วย
ขั้นตอนที่ 1: เพิ่มการเชื่อมโยงข้อมูลสำหรับ GameViewModel
ในขั้นตอนนี้ คุณจะเชื่อมโยง GameViewModel กับไฟล์เลย์เอาต์ที่เกี่ยวข้อง game_fragment.xml
- ใน
game_fragment.xmlให้เพิ่มตัวแปรการเชื่อมโยงข้อมูลประเภทGameViewModelหากมีข้อผิดพลาดใน Android Studio ให้ล้างและสร้างโปรเจ็กต์ใหม่
<layout ...>
<data>
<variable
name="gameViewModel"
type="com.example.android.guesstheword.screens.game.GameViewModel" />
</data>
<androidx.constraintlayout...
- ในไฟล์
GameFragmentให้ส่งGameViewModelไปยังการเชื่อมโยงข้อมูล
โดยกำหนดviewModelให้กับตัวแปรbinding.gameViewModelที่คุณประกาศไว้ในขั้นตอนก่อนหน้า วางโค้ดนี้ไว้ภายในonCreateView()หลังจากเริ่มต้นviewModelหากมีข้อผิดพลาดใน Android Studio ให้ล้างและสร้างโปรเจ็กต์ใหม่
// Set the viewmodel for databinding - this allows the bound layout access
// to all the data in the ViewModel
binding.gameViewModel = viewModelขั้นตอนที่ 2: ใช้การเชื่อมโยง Listener สำหรับการจัดการเหตุการณ์
การเชื่อมโยง Listener คือนิพจน์การเชื่อมโยงที่ทำงานเมื่อมีการทริกเกอร์เหตุการณ์ เช่น onClick(), onZoomIn() หรือ onZoomOut() การเชื่อมโยง Listener จะเขียนเป็นนิพจน์ Lambda
การเชื่อมโยงข้อมูลจะสร้าง Listener และตั้งค่า Listener ในมุมมอง เมื่อเกิดเหตุการณ์ที่รอฟัง Listener จะประเมินนิพจน์ Lambda การเชื่อมโยง Listener จะทำงานร่วมกับปลั๊กอิน Android Gradle เวอร์ชัน 2.0 ขึ้นไป ดูข้อมูลเพิ่มเติมได้ที่เลย์เอาต์และนิพจน์การเชื่อมโยง
ในขั้นตอนนี้ คุณจะแทนที่เครื่องมือฟังการคลิกใน GameFragment ด้วยการเชื่อมโยงเครื่องมือฟังในไฟล์ game_fragment.xml
- ใน
game_fragment.xmlให้เพิ่มแอตทริบิวต์onClickลงในskip_buttonกำหนดนิพจน์การเชื่อมโยงและเรียกใช้เมธอดonSkip()ในGameViewModelนิพจน์การเชื่อมโยงนี้เรียกว่าการเชื่อมโยง Listener
<Button
android:id="@+id/skip_button"
...
android:onClick="@{() -> gameViewModel.onSkip()}"
... />- ในทำนองเดียวกัน ให้เชื่อมโยงเหตุการณ์คลิกของ
correct_buttonกับเมธอดonCorrect()ในGameViewModel
<Button
android:id="@+id/correct_button"
...
android:onClick="@{() -> gameViewModel.onCorrect()}"
... />- เชื่อมโยงเหตุการณ์คลิกของ
end_game_buttonกับเมธอดonGameFinish()ในGameViewModel
<Button
android:id="@+id/end_game_button"
...
android:onClick="@{() -> gameViewModel.onGameFinish()}"
... />- ใน
GameFragmentให้นำคำสั่งที่ตั้งค่าเครื่องมือตรวจหาการคลิกออก และนำฟังก์ชันที่เครื่องมือตรวจหาการคลิกเรียกใช้ออก คุณไม่จำเป็นต้องใช้แล้ว
โค้ดที่จะนำออก
binding.correctButton.setOnClickListener { onCorrect() }
binding.skipButton.setOnClickListener { onSkip() }
binding.endGameButton.setOnClickListener { onEndGame() }
/** Methods for buttons presses **/
private fun onSkip() {
viewModel.onSkip()
}
private fun onCorrect() {
viewModel.onCorrect()
}
private fun onEndGame() {
gameFinished()
}ขั้นตอนที่ 3: เพิ่มการเชื่อมโยงข้อมูลสำหรับ ScoreViewModel
ในขั้นตอนนี้ คุณจะเชื่อมโยง ScoreViewModel กับไฟล์เลย์เอาต์ที่เกี่ยวข้อง score_fragment.xml
- ในไฟล์
score_fragment.xmlให้เพิ่มตัวแปรการเชื่อมโยงประเภทScoreViewModelขั้นตอนนี้คล้ายกับที่คุณทำสำหรับGameViewModelด้านบน
<layout ...>
<data>
<variable
name="scoreViewModel"
type="com.example.android.guesstheword.screens.score.ScoreViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout- ใน
score_fragment.xmlให้เพิ่มแอตทริบิวต์onClickลงในplay_again_buttonกำหนดการเชื่อมโยง Listener และเรียกใช้เมธอดonPlayAgain()ในScoreViewModel
<Button
android:id="@+id/play_again_button"
...
android:onClick="@{() -> scoreViewModel.onPlayAgain()}"
... />- ใน
ScoreFragmentภายในonCreateView()ให้เริ่มต้นviewModelจากนั้นเริ่มต้นตัวแปรการเชื่อมโยงbinding.scoreViewModel
viewModel = ...
binding.scoreViewModel = viewModel- ใน
ScoreFragmentให้นำโค้ดที่ตั้งค่าเครื่องมือฟังการคลิกสำหรับplayAgainButtonออก หาก Android Studio แสดงข้อผิดพลาด ให้ล้างและสร้างโปรเจ็กต์ใหม่
โค้ดที่จะนำออก
binding.playAgainButton.setOnClickListener { viewModel.onPlayAgain() }- เรียกใช้แอป แอปควรทำงานได้เหมือนเดิม แต่ตอนนี้มุมมองปุ่มจะสื่อสารกับออบเจ็กต์
ViewModelโดยตรง มุมมองจะไม่สื่อสารผ่านตัวแฮนเดิลการคลิกปุ่มในScoreFragmentอีกต่อไป
การแก้ปัญหาข้อความแสดงข้อผิดพลาดในการเชื่อมโยงข้อมูล
เมื่อแอปใช้การเชื่อมโยงข้อมูล กระบวนการคอมไพล์จะสร้างคลาสกลางที่ใช้สำหรับการเชื่อมโยงข้อมูล แอปอาจมีข้อผิดพลาดที่ Android Studio ตรวจไม่พบจนกว่าคุณจะพยายามคอมไพล์แอป ดังนั้นคุณจึงไม่เห็นคำเตือนหรือโค้ดสีแดงขณะเขียนโค้ด แต่ในเวลาคอมไพล์ คุณจะได้รับข้อผิดพลาดที่เข้าใจยากซึ่งมาจากคลาสกลางที่สร้างขึ้น
หากได้รับข้อความแสดงข้อผิดพลาดที่อ่านไม่ออก ให้ทำดังนี้
- ดูข้อความในบานหน้าต่างสร้างของ Android Studio อย่างละเอียด หากเห็นตำแหน่งที่ลงท้ายด้วย
databindingแสดงว่ามีข้อผิดพลาดเกี่ยวกับการเชื่อมโยงข้อมูล - ในไฟล์ XML ของเลย์เอาต์ ให้ตรวจสอบข้อผิดพลาดในแอตทริบิวต์
onClickที่ใช้การเชื่อมโยงข้อมูล มองหาฟังก์ชันที่นิพจน์ Lambda เรียกใช้ และตรวจสอบว่าฟังก์ชันนั้นมีอยู่ - ในส่วน
<data>ของ XML ให้ตรวจสอบการสะกดตัวแปรการเชื่อมโยงข้อมูล
เช่น โปรดสังเกตการสะกดชื่อฟังก์ชัน onCorrect() ผิดในค่าแอตทริบิวต์ต่อไปนี้
android:onClick="@{() -> gameViewModel.onCorrectx()}"
นอกจากนี้ โปรดสังเกตการสะกดคำผิดของ gameViewModel ในส่วน <data> ของไฟล์ XML
<data>
<variable
name="gameViewModelx"
type="com.example.android.guesstheword.screens.game.GameViewModel" />
</data>Android Studio จะไม่ตรวจพบข้อผิดพลาดเช่นนี้จนกว่าคุณจะคอมไพล์แอป จากนั้นคอมไพเลอร์จะแสดงข้อความแสดงข้อผิดพลาด เช่น ข้อความต่อไปนี้
error: cannot find symbol import com.example.android.guesstheword.databinding.GameFragmentBindingImpl" symbol: class GameFragmentBindingImpl location: package com.example.android.guesstheword.databinding
การเชื่อมโยงข้อมูลทํางานได้ดีกับ LiveData ที่ใช้กับออบเจ็กต์ ViewModel เมื่อเพิ่มการเชื่อมโยงข้อมูลไปยังออบเจ็กต์ ViewModel แล้ว คุณก็พร้อมที่จะรวม LiveData
ในงานนี้ คุณจะเปลี่ยนแอป GuessTheWord ให้ใช้ LiveData เป็นแหล่งที่มาของการเชื่อมโยงข้อมูลเพื่อแจ้งให้ UI ทราบเกี่ยวกับการเปลี่ยนแปลงข้อมูลโดยไม่ต้องใช้วิธีการสังเกตการณ์ LiveData
ขั้นตอนที่ 1: เพิ่ม LiveData ของคำลงในไฟล์ game_fragment.xml
ในขั้นตอนนี้ คุณจะเชื่อมโยงมุมมองข้อความของคำปัจจุบันกับออบเจ็กต์ LiveData ใน ViewModel โดยตรง
- ใน
game_fragment.xmlให้เพิ่มแอตทริบิวต์android:textลงในมุมมองข้อความword_text
ตั้งค่าเป็นออบเจ็กต์ LiveData จาก GameViewModel โดยใช้ตัวแปรการเชื่อมโยง gameViewModelword
<TextView
android:id="@+id/word_text"
...
android:text="@{gameViewModel.word}"
... />โปรดทราบว่าคุณไม่จำเป็นต้องใช้ word.value แต่คุณสามารถใช้ออบเจ็กต์ LiveData จริงแทนได้ ออบเจ็กต์ LiveData จะแสดงค่าปัจจุบันของ word หากค่าของ word เป็น Null ออบเจ็กต์ LiveData จะแสดงสตริงว่าง
- ใน
GameFragmentในonCreateView()หลังจากเริ่มต้นgameViewModelแล้ว ให้ตั้งค่ากิจกรรมปัจจุบันเป็นเจ้าของวงจรของตัวแปรbindingซึ่งจะกำหนดขอบเขตของออบเจ็กต์LiveDataด้านบน เพื่อให้ออบเจ็กต์อัปเดตมุมมองในเลย์เอาต์game_fragment.xmlได้โดยอัตโนมัติ
binding.gameViewModel = ...
// Specify the current activity as the lifecycle owner of the binding.
// This is used so that the binding can observe LiveData updates
binding.lifecycleOwner = this- ใน
GameFragmentให้นำผู้สังเกตการณ์สำหรับLiveDatawordออก
โค้ดที่จะนำออก
/** Setting up LiveData observation relationship **/
viewModel.word.observe(this, Observer { newWord ->
binding.wordText.text = newWord
})- เรียกใช้แอปและเล่นเกม ตอนนี้ระบบจะอัปเดตคำปัจจุบันโดยไม่มีเมธอด Observer ในตัวควบคุม UI
ขั้นตอนที่ 2: เพิ่ม LiveData ของคะแนนลงในไฟล์ score_fragment.xml
ในขั้นตอนนี้ คุณจะเชื่อมโยง LiveData score กับมุมมองข้อความคะแนนในส่วนคะแนน
- ใน
score_fragment.xmlให้เพิ่มแอตทริบิวต์android:textลงในมุมมองข้อความคะแนน กำหนดscoreViewModel.scoreให้กับแอตทริบิวต์textเนื่องจากscoreเป็นจำนวนเต็ม ให้แปลงเป็นสตริงโดยใช้String.valueOf()
<TextView
android:id="@+id/score_text"
...
android:text="@{String.valueOf(scoreViewModel.score)}"
... />- ใน
ScoreFragmentหลังจากเริ่มต้นscoreViewModelแล้ว ให้ตั้งค่ากิจกรรมปัจจุบันเป็นเจ้าของวงจรของตัวแปรbinding
binding.scoreViewModel = ...
// Specify the current activity as the lifecycle owner of the binding.
// This is used so that the binding can observe LiveData updates
binding.lifecycleOwner = this- ใน
ScoreFragmentให้นำ Observer สำหรับออบเจ็กต์scoreออก
โค้ดที่จะนำออก
// Add observer for score
viewModel.score.observe(this, Observer { newScore ->
binding.scoreText.text = newScore.toString()
})- เรียกใช้แอปและเล่นเกม โปรดสังเกตว่าคะแนนในส่วนคะแนนจะแสดงอย่างถูกต้องโดยไม่มี Observer ในส่วนคะแนน
ขั้นตอนที่ 3: เพิ่มการจัดรูปแบบสตริงด้วยการเชื่อมโยงข้อมูล
ในเลย์เอาต์ คุณสามารถเพิ่มการจัดรูปแบบสตริงพร้อมกับการเชื่อมโยงข้อมูลได้ ในงานนี้ คุณจะจัดรูปแบบคำปัจจุบันเพื่อเพิ่มเครื่องหมายคำพูดรอบคำ นอกจากนี้ คุณยังจัดรูปแบบสตริงคะแนนให้มีคำนำหน้าเป็น คะแนนปัจจุบัน ได้ด้วย ดังที่แสดงในรูปภาพต่อไปนี้

- ใน
string.xmlให้เพิ่มสตริงต่อไปนี้ ซึ่งคุณจะใช้เพื่อจัดรูปแบบมุมมองข้อความwordและscore%sและ%dเป็นตัวยึดตำแหน่งสำหรับคำปัจจุบันและคะแนนปัจจุบัน
<string name="quote_format">\"%s\"</string>
<string name="score_format">Current Score: %d</string>- ใน
game_fragment.xmlให้อัปเดตแอตทริบิวต์textของมุมมองข้อความword_textเพื่อใช้ทรัพยากรสตริงquote_formatผ่านในgameViewModel.wordซึ่งจะส่งคำปัจจุบันเป็นอาร์กิวเมนต์ไปยังสตริงการจัดรูปแบบ
<TextView
android:id="@+id/word_text"
...
android:text="@{@string/quote_format(gameViewModel.word)}"
... />- จัดรูปแบบมุมมองข้อความ
scoreให้คล้ายกับword_textในgame_fragment.xmlให้เพิ่มแอตทริบิวต์textลงในมุมมองข้อความscore_textใช้ทรัพยากรสตริงscore_formatซึ่งรับอาร์กิวเมนต์ที่เป็นตัวเลข 1 รายการซึ่งแสดงโดยตัวยึดตำแหน่ง%dส่งออบเจ็กต์LiveData,scoreเป็นอาร์กิวเมนต์ไปยังสตริงการจัดรูปแบบนี้
<TextView
android:id="@+id/score_text"
...
android:text="@{@string/score_format(gameViewModel.score)}"
... />- ในคลาส
GameFragmentภายในเมธอดonCreateView()ให้นำโค้ด Observerscoreออก
โค้ดที่จะนำออก
viewModel.score.observe(this, Observer { newScore ->
binding.scoreText.text = newScore.toString()
})- ล้างข้อมูล สร้างใหม่ และเรียกใช้แอป แล้วเล่นเกม โปรดสังเกตว่าคำปัจจุบันและคะแนนจะจัดรูปแบบในหน้าจอเกม

ยินดีด้วย คุณได้ผสานรวม LiveData และ ViewModel กับการเชื่อมโยงข้อมูลในแอปแล้ว ซึ่งจะช่วยให้มุมมองในเลย์เอาต์สื่อสารกับ ViewModel ได้โดยตรงโดยไม่ต้องใช้ตัวแฮนเดิลการคลิกใน Fragment นอกจากนี้ คุณยังใช้LiveDataออบเจ็กต์เป็นแหล่งที่มาของการเชื่อมโยงข้อมูลเพื่อแจ้งให้ UI ทราบโดยอัตโนมัติเกี่ยวกับการเปลี่ยนแปลงในข้อมูลโดยไม่ต้องใช้LiveDataเมธอด Observer
โปรเจ็กต์ Android Studio: GuessTheWord
- Data Binding Library ทำงานร่วมกับ Android Architecture Components เช่น
ViewModelและLiveDataได้อย่างราบรื่น - เลย์เอาต์ในแอปสามารถเชื่อมโยงกับข้อมูลใน Architecture Components ซึ่งช่วยให้คุณจัดการวงจรของตัวควบคุม UI และแจ้งเตือนเกี่ยวกับการเปลี่ยนแปลงในข้อมูลได้อยู่แล้ว
การเชื่อมโยงข้อมูล ViewModel
- คุณเชื่อมโยง
ViewModelกับเลย์เอาต์ได้โดยใช้การเชื่อมโยงข้อมูล ViewModelจะเก็บข้อมูล UI การส่งออบเจ็กต์ViewModelไปยังการเชื่อมโยงข้อมูลจะช่วยให้คุณทำให้การสื่อสารบางอย่างระหว่างมุมมองกับออบเจ็กต์ViewModelเป็นแบบอัตโนมัติได้
วิธีเชื่อมโยง ViewModel กับเลย์เอาต์
- ในไฟล์เลย์เอาต์ ให้เพิ่มตัวแปรการเชื่อมโยงข้อมูลประเภท
ViewModel
<data>
<variable
name="gameViewModel"
type="com.example.android.guesstheword.screens.game.GameViewModel" />
</data>- ใน
GameFragmentให้ส่งGameViewModelไปยังการเชื่อมโยงข้อมูล
binding.gameViewModel = viewModelการเชื่อมโยง Listener
- การเชื่อมโยง Listener คือนิพจน์การเชื่อมโยงในเลย์เอาต์ที่ทํางานเมื่อมีการทริกเกอร์เหตุการณ์คลิก เช่น
onClick() - การเชื่อมโยง Listener จะเขียนเป็นนิพจน์ Lambda
- การใช้การเชื่อมโยง Listener จะเป็นการแทนที่ Listener การคลิกในตัวควบคุม UI ด้วยการเชื่อมโยง Listener ในไฟล์เลย์เอาต์
- การเชื่อมโยงข้อมูลจะสร้าง Listener และตั้งค่า Listener ในมุมมอง
android:onClick="@{() -> gameViewModel.onSkip()}"การเพิ่ม LiveData ลงในการเชื่อมโยงข้อมูล
- ออบเจ็กต์
LiveDataสามารถใช้เป็นแหล่งที่มาของการเชื่อมโยงข้อมูลเพื่อแจ้งให้ UI ทราบโดยอัตโนมัติเกี่ยวกับการเปลี่ยนแปลงในข้อมูล - คุณเชื่อมโยงมุมมองกับออบเจ็กต์
LiveDataในViewModelได้โดยตรง เมื่อLiveDataในViewModelเปลี่ยนแปลง มุมมองในเลย์เอาต์จะอัปเดตโดยอัตโนมัติได้โดยไม่ต้องใช้วิธีการสังเกตการณ์ในตัวควบคุม UI
android:text="@{gameViewModel.word}"- หากต้องการให้
LiveDataการเชื่อมโยงข้อมูลทํางาน ให้ตั้งค่ากิจกรรมปัจจุบัน (ตัวควบคุม UI) เป็นเจ้าของวงจรของตัวแปรbindingในตัวควบคุม UI
binding.lifecycleOwner = thisการจัดรูปแบบสตริงด้วยการเชื่อมโยงข้อมูล
- การใช้การเชื่อมโยงข้อมูลช่วยให้คุณจัดรูปแบบทรัพยากรสตริงด้วยตัวยึดตำแหน่ง เช่น
%sสำหรับสตริง และ%dสำหรับจำนวนเต็ม - หากต้องการอัปเดตแอตทริบิวต์
textของมุมมอง ให้ส่งออบเจ็กต์LiveDataเป็นอาร์กิวเมนต์ไปยังสตริงการจัดรูปแบบ
android:text="@{@string/quote_format(gameViewModel.word)}"หลักสูตร Udacity:
เอกสารประกอบสำหรับนักพัฒนาแอป Android
ส่วนนี้แสดงรายการการบ้านที่เป็นไปได้สำหรับนักเรียน/นักศึกษาที่กำลังทำ Codelab นี้เป็นส่วนหนึ่งของหลักสูตรที่สอนโดยผู้สอน ผู้สอนมีหน้าที่ดำเนินการต่อไปนี้
- มอบหมายการบ้านหากจำเป็น
- สื่อสารกับนักเรียนเกี่ยวกับวิธีส่งงานที่ได้รับมอบหมาย
- ให้คะแนนงานการบ้าน
ผู้สอนสามารถใช้คำแนะนำเหล่านี้ได้มากน้อยตามที่ต้องการ และควรมีอิสระในการมอบหมายการบ้านอื่นๆ ที่เห็นว่าเหมาะสม
หากคุณกำลังทำ Codelab นี้ด้วยตนเอง โปรดใช้แบบฝึกหัดเหล่านี้เพื่อทดสอบความรู้ของคุณ
ตอบคำถามต่อไปนี้
คำถามที่ 1
ข้อความใดต่อไปนี้ไม่เป็นจริงเกี่ยวกับการเชื่อมโยง Listener
- การเชื่อมโยง Listener คือนิพจน์การเชื่อมโยงที่ทํางานเมื่อเกิดเหตุการณ์
- การเชื่อมโยง Listener ใช้ได้กับปลั๊กอิน Android Gradle ทุกเวอร์ชัน
- การเชื่อมโยง Listener จะเขียนเป็นนิพจน์ Lambda
- การเชื่อมโยง Listener จะคล้ายกับการอ้างอิงเมธอด แต่จะช่วยให้คุณเรียกใช้นิพจน์การเชื่อมโยงข้อมูลที่กำหนดเองได้
คำถามที่ 2
สมมติว่าแอปของคุณมีแหล่งข้อมูลสตริงนี้<string name="generic_name">Hello %s</string>
ไวยากรณ์ที่ถูกต้องสำหรับการจัดรูปแบบสตริงโดยใช้นิพจน์การเชื่อมโยงข้อมูลคือข้อใดต่อไปนี้
android:text= "@{@string/generic_name(user.name)}"android:text= "@{string/generic_name(user.name)}"android:text= "@{@generic_name(user.name)}"android:text= "@{@string/generic_name,user.name}"
คำถามที่ 3
ระบบจะประเมินและเรียกใช้นิพจน์ที่เชื่อมโยงกับ Listener เมื่อใด
- เมื่อมีการเปลี่ยนแปลงข้อมูลที่
LiveDataถือครองอยู่ - เมื่อมีการสร้างกิจกรรมขึ้นมาใหม่เนื่องจากการเปลี่ยนแปลงการกำหนดค่า
- เมื่อเกิดเหตุการณ์ เช่น
onClick() - เมื่อกิจกรรมเข้าสู่เบื้องหลัง
เริ่มบทเรียนถัดไป:
ดูลิงก์ไปยัง Codelab อื่นๆ ในหลักสูตรนี้ได้ที่หน้า Landing Page ของ Codelab หลักพื้นฐานของ Android Kotlin


