Android Kotlin Fundamentals 05.2 #4 : Task: Encapsulate the LiveData

캡슐화는 오브젝트의 필드 중 일부에 대한 직접 접근을 제한하는 방법입니다. 오브젝트를 캡슐화 할 때, private 변수를 set 할 수 있는 public 메소드에 접근 할 수 있도록 합니다. 캡슐화를 사용하면 다른 클래스가 내부의 변수를 조작하는 방법을 제어 할 수 있습니다.

 

현재 코드는 외부 클래스가 score 데이터와 word 데이터를 value 프로퍼티에 접근 하여 수정 할 수 있습니다. (예를 들어 viewModel.score.value) 이것은 해당 코드랩에서는 문제가 되지 않지만, 프로덕션 앱에서는 ViewModel안에서 데이터를 제어 해야 할 수도 있습니다.

 

오직 ViewModel만 데이터를 수정할 수 있어야 하지만, UI Controller는 데이터를 읽을 수 있어야 합니다. 그래서 data들이 private 접근 지시자로 설정되어서는 안됩니다. 데이터들을 캡슐화 하기 위해 MutableLiveData와 LiveData를 사용해야 합니다.

 

MutableLiveData와 LiveData:

 

  • 이름이 암시 하듯 MutableLiveData안의 데이터는 변경 될 수 있습니다. (*Mutable - 변할 수 있는) ViewModel 안에서 해당 데이터는 수정 될 수 있습니다.
  • LiveData는 읽을 수 있지만, 변경은 되지 않습니다. ViewModel 외부에서 데이터를 읽을 수 있으나, 수정되지 않게 하려면 LiveData를 통해 외부에 해당 데이터를 제공 해야 합니다.

해당 방법을 사용하려면 Kotlin backing property를 사용해야 합니다. backing property는 gettter를 통해 다른 값을 리턴 할 수 있도록 해준다. 이번 태스크에서 score와 word 오브젝트에 대한 backing property를 구현 할 것 입니다.

 

Add a backing property to score and word


1. GameViewModel에서 score를 데이터를 private로 변경 합니다.

 

2. backing properties에서 네이밍 컨벤션을 적용하기 위해 score를 _score로 변경 합니다. _score는 현재 mutable 버전 입니다. private로 선언되어 있어 내부에서 읽거나 값을 변경 할 수 있습니다.

 

3. public 버전의 LiveData인 score를 정의 합니다.

 

// The current score
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>

 

4. LiveData를 선언 하면, 초기화 에러가 발생하게 되는데, score 데이터는 LiveData참조 이기 때문에, 더이상 데이터를 set할 수 없기 때문에 발생 합니다. 그래서 LiveData형인 score의 get()을 오버라이드 해서 GameViewModel의 _score를 리턴 해 줍니다.

 

LiveData는 이제 값을 셋팅하지 못하기 때문에 get()시 _score를 리턴 합니다. MutableLiveData인 _score를 리턴 하더라도 LiveData는 값을 설정하지 못하도록 되어 있기 때문에 읽는 것만 가능 합니다.

val score: LiveData<Int>
   get() = _score

 

5. GameViewModel에서 score 데이터를 참조 했던 부분을 MutableLiveData형태인 _score로 변경해 줍니다.

 

init {
   ...
   _score.value = 0
   ...
}

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

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

 

6. word MutableLiveData도 _word로 이름을 변경 한 후 word라는 LiveData를 생성합니다.

// The current word
private val _word = MutableLiveData<String>()
val word: LiveData<String>
   get() = _word
...
init {
   _word.value = ""
   ...
}
...
private fun nextWord() {
   if (!wordList.isEmpty()) {
       //Select and remove a word from the list
       _word.value = wordList.removeAt(0)
   }
}

 

 

지금까지 LiveData를 사용해서 word와 score를 캡슐화 해 보았습니다.

댓글



Designed by JB FACTORY