Android LiveData ViewModel
안녕하세요.
오늘은 LiveData 와 ViewModel 에 대하여 이야기해보겠습니다.
(해당 링크는 Android developers 원문입니다.)
정의
ViewModel 은 UI 컨트롤러의 도우미 클래스 이다.
LiveData 는 활성화 상태일때 값의 변화가 있다면,
관찰자가 값의 변경을 감지한다.
LiveData 의 장점
- UI와 데이터 상태의 일치 보장
- 메모리 누수 없음
- 중지된 활동으로 인한 비정상 종료 없음
- 수명 주기를 더 이상 수동으로 처리하지 않음
- 최신 데이터 유지
- 적절한 구성 변경
- 리소스 공유
정리 하면...이걸 사용해라. - 01
ViewModel 의 장점
- 수명 주기를 고려, UI 관련 데이터를 저장하고 관리하도록 설계
- 화면 회전과 같이 구성을 변경할 때 데이터 유지
정리 하면...이걸 사용해라. - 02
ViewModel 의 수명 주기
ViewModel 객체의 범위는 ViewModel 을 가져올 때
ViewModelProvider 에 전달되는 Lifecycle 로 지정됩니다.
ViewModel 은 범위가 지정된 Lifecycle 이 영구적으로 경과될 때까지,
즉 Activity 에서는 Activity 가 끝날 때까지
그리고
Fragment 에서는 Fragment 가 분리될 때까지
메모리에 남아 있습니다.
정리 하면...이걸 사용해라. - 03
Sample Code - 블로그 주인장이 직접 코딩했음 !
저는 입력값 (EditText) 두 개를 합 하여 나타내 주는 (TextView) 것을 보여드리겠습니다.
그런데. 이 기능을 하기 위해서 LiveData 와 ViewModel 을 사용해야 하는가?
그렇지 않습니다.
하지만, 저는 이것을 왜 했냐면. 각각의 기능에 대해서 좀 더 알기 위해서 만들어봤습니다.
먼저... Manifests 파일에 Activity 를 추가해야 합니다.
일부러 회전이 가능하도록 screenOrientation 값을 할당하지 않았습니다.
<activity android:name=".activity.SumActivity" />
다음은 하단 이미지처럼 layout 파일이 필요합니다.
(layout.xml 코드를 모두 올렸는데.... 이 정도는 만드시겠지 하고 패스했습니다.. ;; )
자 그럼 남은 작업은 두 개의 파일을 더 만들면 됩니다.
1. Activity ( 파일명 : SumActivity.kt )
2. ViewModel ( 파일명 : SumViewModel.kt )
package com.example.defaultkotlin.activity
import android.os.Bundle
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.example.defaultkotlin.CommonActivity
import com.example.defaultkotlin.databinding.ActivitySumBinding
import com.example.defaultkotlin.viewmodel.SumViewModel
import common.LogUtil
class SumActivity : CommonActivity() {
private lateinit var binding: ActivitySumBinding
private lateinit var viewModel: SumViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySumBinding.inflate(layoutInflater)
setContentView(binding.root)
LogUtil.iOnCreate()
initSum()
}
private fun initSum() {
viewModel = ViewModelProvider(this).get(SumViewModel::class.java)
val observer = Observer<String> { textValue ->
// add other UI Update code
binding.txtMyView.text = textValue
LogUtil.d("textValue : $textValue")
}
viewModel.getSumValue().observe(this, observer)
binding.btnSum.setOnClickListener {
viewModel.setSumValue(
Integer.parseInt(binding.edtFirst.text.toString()),
Integer.parseInt(binding.edtSecond.text.toString())
)
}
}
override fun onDestroy() {
super.onDestroy()
LogUtil.e("onDestroy...")
}
}
package com.example.defaultkotlin.viewmodel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import common.LogUtil
class SumViewModel : ViewModel() {
init {
LogUtil.d("init() : MyViewModel...")
}
override fun onCleared() {
super.onCleared()
LogUtil.d("MyViewModel destroyed!")
}
private val strSumValue: MutableLiveData<String> by lazy {
MutableLiveData<String>()
}
fun getSumValue() = strSumValue
fun setSumValue(a: Int, b: Int) {
strSumValue.value = (a + b).toString()
}
}
Android 에서 화면 전환 시 onDestroy -> onCreate 가 일어나게 된다.
그러나 이러한 방법을 사용하면 데이터 유실이 되지 않는다.
하단 로그가 그것을 증명해준다.