LiveData은 무엇이고 왜 사용할까?
LiveData는 Data의 변경을 관찰할 수 있는 Data Holder 클래스입니다.
(LiveData is lifecycle aware observable data holder class)
lifecycle aware
app components인 activities, fragments, or services 들의 생명 주기를 고려합니다.(lifecycle aware)
lifecycle aware를 한 특징으로 인해 active 한 생명 주기를 가진 관찰자만(activities, fragments, or services) 업데이트할 수 있습니다.
** Observer (관찰자)란 LiveData가 가지고 있는 데이터 변화를 관찰하는 대상입니다.
데이터가 변할 때마다 이벤트를 받을 수 있습니다.
** active 한 생명 주기란 관찰자의 생명주기가 STARTED 또는 RESUMED 상태인 것을 의미합니다.
라이프 사이클을 다루는 코드를 직접 작성할 필요가 없습니다.
LiveData는 lifecycle를 인지해서 앱 컴포넌트가 inacitve 한 상태로 바뀌면 자기 자신을 메모리 상에서 지우고, 관찰자는 어떤 LiveData 이벤트도 받지 않습니다.
→ 메모리 누수, activity 또는 fragment가 destory될 때 crash가 발생하는 것을 방지할 수 있습니다.
observable data holder
Data의 변경을 관찰 할 수 있는 Data Holder 클래스입니다.
LiveData는 데이터를 보관합니다. LiveData는 모든 데이터와 함께 사용할 수 있는 wrapper(포장지)입니다.
activity, fragment, service 등은 livedate의 observer 역할을 해서 앱의 데이터가 바뀌면 자동으로 UI를 수정할 수 있습니다.
해야할 것
이전에 Viewmodel을 사용한 더하기 샘플을 만들어 봤습니다.
이 예제를 기반으로 LiveData를 사용해볼 것입니다.
develop-writing.tistory.com/43
사용자가 입력하고 더하면 덧셈의 결과가 계속 증가합니다.
우리가 할 것은
1. MainActivityViewModel의 덧셈의 결과 데이터를 LiveData 객체로 변환하는 방법에 대해 알아볼 것입니다
2. LiveData 개체에 관찰자를 추가하고 LiveData를 관찰하는 방법에 대해 알아볼 것입니다.
덧셈의 결과 데이터를 LiveData 객체로 변환하기
LiveData 생성하기
MutableLiveData는 값을 변경할 수 있는 LiveData입니다. MutableLiveData는 generic 클래스이므로 이 클래스가 보유하는 데이터 유형을 지정해야 합니다. 이제 덧셈의 결과가 LiveData에 객체로 변환됐습니다.
// 현재 덧셈 결과 값
private var count = MutableLiveData<Int>()
LiveData 초기 값 설정하기
MainActivityViewModel의 init block 안에서 덧셈의 결과를 초기화합니다. LiveData 변수의 값을 변경하려면 변수에 setValue() 메서드를 사용합니다.
Kotlin에서는 value property를 사용하여 setValue()를 호출할 수 있습니다. 여기서는 뷰 모델 생성할 때 사용한 초기값을 LiveData의 값으로 하겠습니다.
class MainActivityViewModel(startingTotal: Int) :ViewModel() {
private var count = MutableLiveData<Int>()
init {
count.value = startingTotal
}
...
}
LiveData 값 수정하기
null check을 추가하여 getUpdatedCount()에 count.value를 추가합니다. 그런 다음 점수에서 plus() 함수를 호출하여 null-safety하게 덧셈을 합니다.
fun getUpdatedCount(plusCount: Int){
count.value = (count.value)?.plus(plusCount)
}
LiveData 캡슐화, 은닉화(Encapsulation)하기 (= 접근 제어하기)
캡슐화는 객체의 일부 필드에 대한 직접 액세스를 제한하는 방법입니다.
객체를 캡슐화할 때 private 내부 필드를 수정하는 public method를 표시합니다.
캡슐화를 사용하여 다른 클래스가 이러한 내부 필드를 조작하는 방법을 제어합니다.
// MutableLiveData를 은닉하기
private var count = MutableLiveData<Int>()
// 다른 클래스가 접근할 수 있는 데이터
val countData : LiveData<Int>
get() = count
viewmodel 전체 소스는 다음과 같습니다.
class MainActivityViewModel(startingTotal: Int) :ViewModel() {
// MutableLiveData를 은닉하기
private var count = MutableLiveData<Int>()
// 다른 클래스가 접근할 수 있는 데이터
val countData : LiveData<Int>
get() = count
// 초기 값 설정하기
init {
count.value = startingTotal
}
// 덧셈 결과 값 수정하기
fun getUpdatedCount(plusCount: Int){
count.value = (count.value)?.plus(plusCount)
}
}
LiveData 객체에 관찰자를 추가하고 LiveData를 관찰하기
관찰자에게(현재는 activity) 현재 덧셈 총합의 LiveData 객체를 더합니다.
observer() method를 뷰 모델 초기화한 이후에 사용합니다. 람다식을 사용해 코드를 단순화 합니다.
viewModelFactory = MainActivityViewModelFactory(1234)
viewModel = ViewModelProvider(this, viewModelFactory).get(MainActivityViewModel::class.java)
viewModel.countData.observe(this, Observer {
binding.countText.text = it.toString()
})
MainActivity의 전체 소스는 다음과 같습니다.
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var viewModel: MainActivityViewModel
private lateinit var viewModelFactory: MainActivityViewModelFactory
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
viewModelFactory = MainActivityViewModelFactory(1234)
viewModel = ViewModelProvider(this, viewModelFactory).get(MainActivityViewModel::class.java)
viewModel.countData.observe(this, Observer {
binding.countText.text = it.toString()
})
binding.button.setOnClickListener {
viewModel.getUpdatedCount(Integer.parseInt(binding.countEt.text.toString()))
}
}
}
코드를 실행하면 다음과 같이 나옵니다.
덧셈 결과가 수정될 때마다 UI에 업데이트됩니다.
전체 소스는 깃헙에서 확인할 수 있습니다.
github.com/keepseung/Android-Blog-Source
참고:developer.android.com/topic/libraries/architecture/livedata
developer.android.com/codelabs/kotlin-android-training-live-data#4
'Android > Jetpack, Clean Architecture' 카테고리의 다른 글
Android 양방향 데이터 바인딩 사용하기 (Two-way DataBinding With LiveData) (0) | 2021.02.16 |
---|---|
DataBinding에 ViewModel, LiveData와 함께 사용하기 (0) | 2021.02.16 |
[안드로이드/Android] ViewModel 사용하기 (0) | 2021.01.20 |
[안드로이드/Android] Databinding 사용하기 (0) | 2021.01.20 |
모던 안드로이드 앱 만들기 (3) - Retrofit, RxJava를 이용한 네트워크 통신 (0) | 2021.01.18 |