첫 번째로 ViewModel에 LiveData를 적용해 볼 것이다.
LiveData는 생명 주기를 인지하는 관찰 가능한 데이터 홀더 클래스이다.
예를 들어, 우리는 이 앱에서 현재 점수를 LiveData로 감쌀 수 있다.
이번 코드랩에서는 LiveData의 여러 특성을 배울 것이다.
- LiveData는 관찰 가능하다.
이 뜻은 LiveData 객체가 가지고 있는 데이터가 변경될 때 observer에게 감지된다는 의미이다.
- LiveData는 데이터를 가지고 있다.
LiveData는 wrapper이고 모든 데이터와 같이 사용될 수 있다.
- LiveData는 생명 주기를 인식한다.
LiveData에 observer를 붙일 때, observer는 LifecycleOwner와 연계되어 있다.
(LifecycleOwner는 주로 Activity나 Fragment 이다)
LiveData는 활성 상태(active lifecycle state)에 있는 observer만 업데이트한다.
1. score와 word를 LiveData를 사용하도록 변경한다.
먼저 GameViewModel 클래스에서 word와 score를 MutableLiveData로 타입을 변경한다.
// The current word
val word = MutableLiveData<String>()
// The current score
val score = MutableLiveData<Int>()
MutableLiveData는 LiveData인데 값이 변경가능하다.
또, MutableLiveData는 generic 클래스이기 때문에 데이터 타입을 정의해주어야 한다.
GameViewModel에서 초기화 블럭 안에 score와 word를 초기화한다.
LiveData 변수의 값을 변경하기 위해서는 변수에 setValue() 메소드를 사용해야 한다.
코틀린에서는 메소드 대신 value property를 사용해 호출할 수 있다.
init {
word.value = ""
score.value = 0
...
}
2. LiveData 객체 참조를 업데이트한다.
이제 score와 word 변수는 LiveData 타입이다.
이번에는 이 변수들의 참조를 value property를 사용해 바꿔볼 것이다.
GameViewModel에서 onSkip() 메소드 안에 score를 score.value로 바꾼다.
이 때, score가 null일 수 있다는 에러를 만나게 되는데 이는 다음에 고칠 것이다.
에러를 해결하기 위해서는 score.value에 null check를 추가해주어야 한다.
그 다음 null-safety와 함께 수행하기 위한 minus() 함수를 호출한다.
onCorrect() 메소드도 같은 방식으로 바꿔준다.
fun onSkip() {
score.value = (score.value)?.minus(1)
nextWord()
}
fun onCorrect() {
score.value = (score.value)?.plus(1)
nextWord()
}
GameViewModel의 nextWord() 메소드 안에서 word 참조를 word.value로 바꿔준다.
private fun nextWord() {
if (!wordList.isEmpty()) {
//Select and remove a word from the list
word.value = wordList.removeAt(0)
}
}
GameFragment의 updateWordText() 메소드 안에서 viewModel.word 참조를 viewModel.word.value로 바꿔준다.
/** Methods for updating the UI **/
private fun updateWordText() {
binding.wordText.text = viewModel.word.value
}
updateScoreText() 메소드도 같은 방식으로 바꿔준다.
private fun updateScoreText() {
binding.scoreText.text = viewModel.score.value.toString()
}
마지막으로 GameFragment의 gameFinished() 메소드 안에서 viewModel.score 참조를
viewModel.score.value로 바꿔주고, null-safety check 부분을 elvis 연산자를 사용해 넣어준다.
private fun gameFinished() {
Toast.makeText(activity, "Game has just finished", Toast.LENGTH_SHORT).show()
val action = GameFragmentDirections.actionGameToScore()
action.score = viewModel.score.value?:0
NavHostFragment.findNavController(this).navigate(action)
}
'Android' 카테고리의 다른 글
Codelab으로 LiveData 알아보기 - 3. Encapsulate the LiveData (0) | 2023.01.26 |
---|---|
Codelab으로 LiveData 알아보기 - 2. Attach observers to the LiveData objects (0) | 2023.01.18 |
Codelab으로 LiveData 알아보기 - 과정 소개 (2) | 2023.01.15 |
Codelab으로 ViewModel 알아보기 - 4. Use a ViewModelFactory(完) (0) | 2023.01.13 |
Codelab으로 ViewModel 알아보기 - 3. Implement click listener (0) | 2023.01.03 |