[android] Live Data

2021. 2. 5. 12:27카테고리 없음

Live Data

라이브 데이터는 라이프 사이클을 인식할 수 있는 관찰가능한 홀더 클래스이다. 라이프 사이클을 인식할 수 있다는 것은 수명 주기를 고려한 다는 의미입니다. 

 

생명주기가 STARTED, RESUMED 상태이면 LiveData는 관찰자를 활성화 상태로 인식합니다. 라이프 사이클이 DESTROYED가 되면 관찰자를 삭제할 수 있습니다. 

 

Live Data 사용의 이점

1. UI 데이터 상태의 일치 보장

앱 데이터 및 라이프 사이클이 변경될 때 마다 observer을 통해 데이터를 변경할 수 있습니다. 

 

2. 메모리 누출 없음

 

연결된 수명 주기가 끝나면 자동으로 삭제됩니다. 

 

3. 중지된 활동으로 인한 비정상 종료 없음

 

관찰자의 수명 주기가 비활성화 상태이면 관찰자는 어떤 Live Data 이벤트도 받지 않음.

 

4. 수명주기를 수동으로 처리하지 않음

 

수명 주기의 변경을 자동으로 인식함으로 수동으로 처리하지 않습니다. 

 

5. 최신 데이터 유지

 

수명 주기가 비활성화 일 경우 다시 활성화가 될 때 새로운 데이터를 받습니다. 

 

 

Live Data 만들기

class NameViewModel : ViewModel() {

    // Create a LiveData with a String
    val currentName: MutableLiveData<String> by lazy {
        MutableLiveData<String>()
    }

    // Rest of the ViewModel...
}

 

일반적으로 LiveData를 관찰하기 시작하는데 가장 좋은 위치는 OnCreate이다. 

 

- Activity, Fragment가 활성화되는 즉시 최신의 데이터를 유지할 수 있기 때문입니다. 

- Activity, Fragment가 OnResume에서 중복호출이 되지 않게 하기 위해서이다. 

 

lass NameActivity : AppCompatActivity() {

    // Use the 'by viewModels()' Kotlin property delegate
    // from the activity-ktx artifact
    private val model: NameViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Other code to setup the activity...

        // Create the observer which updates the UI.
        val nameObserver = Observer<String> { newName ->
            // Update the UI, in this case, a TextView.
            nameTextView.text = newName
        }

        // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
        model.currentName.observe(this, nameObserver)
    }
}

 

name Observer라는 observer 함수를 만들어 주었다. 그리고 currentname이 변경됨을 인식하면 nameObserver가 실행되게 제일 마지막 줄에 등록을 해주었다. 

 

Live Data 객체 업데이트 

button.setOnClickListener {
    val anotherName = "John Doe"
    model.currentName.setValue(anotherName)
}

 

이와 같이 데이터가 변경되게 된다면 위에서 등록된 nameObserver에 의해 TextView에 text가 변경될 것 이다. 

 

 

캡슐화 하기 

LiveData또한 캡슐화가 가능하다. 

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

기존 MutableLiveData의 경우 private로 바꾸어주고 _를 붙여서 ReadData로 변경시켜준다. 

 

추가로 

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

get 함수로 붙여주면 score를 통해 _score를 참조하여 사용할 수 있다. 

 

 

Data Binding 

이전에 xml에 직접적으로 데이터를 연결해서 사용하는 방법을 사용했다. View Model 및 Live Data도 동일하게 사용할 수 있다. 

 

View Model 데이터 바인딩 해주기

<data>

       <variable
           name="gameViewModel"
           type="com.example.android.guesstheword.screens.game.GameViewModel" />
   </data>
   
   
  binding.gameViewModel = viewModel

위와 같이 작성해준 후 

 

OnClick, OnZoomIn, OnZoomOut과 같은 함수를 이용해서 함수를 등록할 수 있다. 

 

<Button
   android:id="@+id/correct_button"
   ...
   android:onClick="@{() -> gameViewModel.onCorrect()}"
   ... />

위와 같이 작성하면 아래와 같은 코드를 삭제할 수 있다. 

binding.correctButton.setOnClickListener { onCorrect() }
binding.skipButton.setOnClickListener { onSkip() }
binding.endGameButton.setOnClickListener { onEndGame() }

 

이럴 경우 Error메세지 보기 

 

1. 안드로이드 스튜디오의 메시지를 잘 확인해본다. 만약 location으로 error메시지가 끝나있다면 데이터 바인딩에서 문제가 발생한 것을 알 수 있다. 

 

Live Data binding하기

데이터를 LiveData로 바인딩한 후 

<TextView
   android:id="@+id/word_text"
   ...
   android:text="@{gameViewModel.word}"
   ... />
   binding.lifecycleOwner = viewLifecycleOwner

 

이런식으로 변경 후 아래와 같은 코드를 지워주어도 원하는 변경이 되면 text가 변경된다. 

 

viewModel.word.observe(viewLifecycleOwner, Observer { newWord ->
   binding.wordText.text = newWord
})

 

Data 자기가 원하는 방식으로 포맷을 정해서도 이용할 수 있습니다. 

 

string.xml

<string name="quote_format">\"%s\"</string>
<string name="score_format">Current Score: %d</string>

view의 xml에 아래와 같이 text에 데이터를 등록할 수 있습니다. 

<TextView
   android:id="@+id/word_text"
   ...
   android:text="@{@string/quote_format(gameViewModel.word)}"
   ... />