Android Kotlin Fundamentals 05.2 #2 : Task : Add LiveData to the GameViewModel 번역

LiveData는 라이프 사이클을 인지하고, 관찰가능한 데이터를 보관하는 클래스 입니다. 예를들어 현재 score 데이터를 LiveData로 감쌀 수 있습니다. 이번 코드랩에서는 LiveData의 여러 특성들에 대해 알아 보겠습니다.

 

  • LiveData는 관찰가능 합니다. 이 의미는 LiveData가 보유한 데이터가 변경되었을 때 observer에 이 변경사항이 전달 됩니다.
  • LiveData는 데이터를 보유할 수 있습니다. LiveData는 어떤 데이터는 감쌀 수 있습니다.
  • LiveData는 라이프사이클을 인지하고 있습니다. 현재 액티브 상태의 라이프사이클 안에서만 observer를 업데이트 합니다.

이번 태스크에서는 GameViewModel의 score 데이터 및 word 데이터를 어떻게 LiveData로 감싸는지 배울 것 입니다. 이후 태스크 에서는 이러한 LiveData에 observer를 추가하고, 해당 LiveData변경을 감지 하는 방법을 배울 것 입니다.

 

Step 1: Change the score and word to use LiveData


1. screens/game 패키지 안에, GameViewModel 파일을 엽니다.

2. score와 word 변수를 MutableLiveData로 변경 합니다.

// The current word
var word = ""

// The current score
var score = 0
// The current word
val word = MutableLiveData<String>()
// The current score
val score = MutableLiveData<Int>()

 

3. GameViewModel의 init 블록 안에서 score와 word를 초기화 시켜줍니다. LiveData의 value를 변경 시키기 위해 setValue() 메소드를 사용해야 합니다. 코틀린에서는 setValue()를 호출해도 되고, value라는 속성에 접근하여 해당 값을 변경 시킬 수 있습니다.

 

init {
        Log.i("GameViewModel", "GameViewModel created");
        word.value = ""
        score.value = 0
        resetList()
        nextWord()
    }

 

Step 2: Update the LiveData object reference


score와 word 변수는 지금 LiveData로 변경 되었습니다. 이번 단계에서는 word, score에 대한 변수의 접근을 LiveData의 value를 통해 접근하도록 변경 하겠습니다.

 

1. GameViewModel의 onSkip()안에서 score로 접근하던 부분을 score.value로 변경해 줍니다. score.value가 null일 수도 있기 때문에 해당 에러를 처리해 주어야 합니다.

 

2. 위의 에러를 처리해 주기 위해 score.value의 null 체크를 추가 줘야 합니다. 그래야 minus() 함수를 호출 할 수 있습니다. 아래 코드와 같이 작성하면  null - safety하게 minus()를 호출 할 수 있습니다.

 

fun onSkip() {
   if (!wordList.isEmpty()) {
       score.value = (score.value)?.minus(1)
   }
   nextWord()
}

 

3. 이번에는 onCorrect() 메소드를 업데이트 해 봅시다. onSkip()를 변경 했을 때랑 비슷 합니다. 다만 minus() 대신 plus()를 사용해 줍니다.

 

fun onCorrect() {
   if (!wordList.isEmpty()) {
       score.value = (score.value)?.plus(1)
   }
   nextWord()
}

 

4. GameViewModel의 nextWord()안에서 word에 대한 참조를 word.value로 바꿔줍니다.

 

private fun nextWord() {
   if (!wordList.isEmpty()) {
       //Select and remove a word from the list
       word.value = wordList.removeAt(0)
   }
}

 

5. GameFramgent의 updateWordText() 안에서 ViewModel.word에 대한 참조를 ViewModel.word.value로 변경해 줍니다.

 

/** Methods for updating the UI **/
private fun updateWordText() {
   binding.wordText.text = viewModel.word.value
}

 

6. GameFragment의 updateScoreText() 안에서 viewModel.score에 대한 참조를 viewModel.score.value로 변경 해 줍니다.

 

private fun updateScoreText() {
   binding.scoreText.text = viewModel.score.value.toString()
}

 

7. GameFragmnet의 gameFinished()안에서 viewModel.score에 대한 참조를 viewModel.score.value로 변경 해 줍니다. null - safey check도 해줍니다.

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)
}

 

8. 여기까지 마쳤을 때, 코드에 에러가 없어야 합니다. 앱을 한번 실행해 보세요. 이번 태스크에서 변경한 앱은 이전과 똑같이 동작해야 합니다.

댓글



Designed by JB FACTORY