-
LiveData안드로이드 학습/Android 기술면접 대비 2024. 9. 23. 15:56
LiveData는 ViewModel을 사용하면서 데이터 처리를 해주었던 기억이 있다. LiveData의 데이터 값의 변경을 관찰하여, View의 값을 자동으로 변하게 하여 최신 데이터를 유지하기 위하여 사용하였다. 하지만 이것 외에는 LiveData에 관한 정확한 이해 없이 사용했기 때문에 이번에 학습을 해보기로 했다.
1. LiveData란?
LiveData는 UI(주로 Activity, Fragment)가 데이터의 변화를 직접적으로 감시하고, 데이터가 변경되면 자동으로 UI가 업데이트될 수 있는 메커니즘을 제공한다. LiveData를 사용한다면 UI와 데이터 사이의 동기화 작업이 간편해진다.
특징 :
- LiveData는 안드로이드에서 제공하는 JetPack 라이브러리 중 하나다.
- LiveData는 관찰 가능한 Data Holder Class 이다.
- LiveData는 LifeCycle을 인식한다.
- 다른 app components (activity, fragments, or services)들의 lifecycle의 데이터 변화를 관찰 가능
- LiveData는 활성상태(active)일때만 데이터를 업데이트 한다. (활성상태 : 수명주기에서의 STARTED, RESUMED)
- LiveData 객체는 Observer 객체와 함께 사용되서, 어떠한 변화가 일어날 경우, LiveData에 등록된 Observer 객체에 변화를 알려주고, Observer의 onChanged() 메소드가 실행되게 된다.
2. LiveData 장점 :
- UI와 데이터 동기화:
- 데이터 변경이 일어날때마다 Observer 객체를 사용하여 변화를 알려준다.
- 메모리 누수 방지 :
- LiveData를 사용하는 컴포넌트가 Destory될 경우 메모리상에서 스스로 해제한다.
- 비정상 종료 방지 :
- 일반적으로 앱에서 UI 구성 요소가 파괴된 후에, 비동기 작업이 완료되었을 때 데이터를 잘못 처리하여 UI를 업데이트 하려는 하려고 한다면 앱에 크래쉬가 발생할 수 있다. 하지만 LiveData는 생명 주기를 인식하기 때문에, 관찰자가 파괴되었을 경우 데이터를 전달하지 않아 비정상 종료를 방지할 수 있다.
- 수명 주기 관리 자동화 :
- 예를 들면 Activity의 수명주기가 STARTED, RESUMED인 상황에서만 데이터 수신. 수명주기가
- 최신 데이터 유지 :
- 수명 주기가 비활성화되면 다시 활성화될 때 최신 데이터를 수신합니다. 예를 들어 백그라운드에 있었던 활동은 포그라운드로 돌아온 직후 최신 데이터를 받습니다.
- 기기 회전 및 구성 변경에도 데이터 유지
- 기기 회전과 같은 구성 변경으로 인해 활동 또는 프래그먼트가 다시 생성되면 사용 가능한 최신 데이터를 즉시 받게 됩니다.
- 리소스 공유
- LiveData를 상속하여 자신만의 LiveData클래스를 구현할 수 있고 싱글톤 패턴을 이용하여 시스템 서비스를 둘러싸면(Wrap) 앱 어디에서나 자원을 공유 할 수 있습니다.
>>> 기존에 내가 알던 데이터의 변화를 인지하는 것 외에도 LiveData는 Activity나 Fragment의 lifecycle을 인지하여 Activity나 Fragment가 종료 되었을때와 시작되어 있을 때의 상황도 인지하여 알아서 처리 해주는게 정말 좋다.
안드로이드는 비정상 종료되는 상황이 정말 다양하다. 안드로이드 os 폰이 너무 다양하기 때문에 같은 앱이라도 어느 폰에서는 에러가 발생하고 어느 폰에서는 정상적으로 잘되는 상황이 있다. 그렇기 때문에 이렇게 수명주기를 자동 관리하고 비정상 종료를 알아서 방지해줘서 생각해야 하는 지점이 줄어들기 때문에 개발자 입장에서는 정말 도움이 많이 될 것 같다.
3. LiveData 사용법 :
LiveData는 주로 ViewModel와 함께 사용된다.
LiveData는 데이터 변경이 가능한 MutableLiveData와 데이터 변경이 불가능한 LiveData가 있다.
- MutableLiveData : 값의 get/set 모두를 할 수 있다.
- LiveData : 값의 get()만을 할 수 있다.
class MvvmSimpleViewModel : ViewModel() { // LiveData 변수 선언 private val _someLiveData = MutableLiveData<Int>() val someLiveData: LiveData<Int> get() = _someLiveData init { _someLiveData.value = 0 } fun plus() { _someLiveData.value = _someLiveData.value?.plus(1) } fun minus() { _someLiveData.value = _someLiveData.value?.minus(1) } }
3-1) LiveData와 MutableLiveData를 나눠서 사용하는 이유 :
- ViewModel과 View의 역할을 분리하기 위함이다. MutableLiveData는 private과 함께 사용해서 ViewModel 이외에서의 데이터 수정을 불가능하게 만들고, ViewModel에서만 MutableLiveData 접근을 통해 데이터 변경을 허용한다.
3-2) setValue()와 postValue() 차이 : (Thread 차이)
- setValue() : Main Thread에서 LiveData 값을 변경해준다. Main Thread에서 바로 값을 변경해주기 때문에 setValue() 함수 호출후 바로 getValue로 값을 읽어올 수 있다. Background에서 호출하면 오류가 걸린다.
- postValue() : Background에서 값을 변경할때 사용한다 (Main Thread가 아닌 상황에서 값을 변경할때). postValue() 호출후 바로 데이터를 가져오려고 하면 변경된 값을 읽어오지 못할 가능성이 있다.
아래 value를 통해 데이터를 변경하는 것은 setValue() 부분이다. postValue() 예제는 나중에 MVVM 패턴을 좀더 깊이 학습해보면서 네트워크 통신 이후 데이터를 변경할 때 만들어봐야겠다.
_someLiveData.value = _someLiveData.value?.plus(1)
mMvvmSimpleViewModel = ViewModelProvider(requireActivity())[MvvmSimpleViewModel::class.java] mMvvmSimpleViewModel.someLiveData.observe(viewLifecycleOwner) { binding.tvMvvmsimpleNumber.text = it.toString() } binding.apply { btnMvvmsimplePlus.setOnClickListener { mMvvmSimpleViewModel.plus() } btnMvvmsimpleMinus.setOnClickListener { mMvvmSimpleViewModel.minus() } }
LiveData 데이트를 관측하는 observe() 메소드를 보면 parameter로 viewLifecycleOwner를 넘겨준다. 이 부분을 통해서 LiveData가 Activity 또는 Fragment가 활성상태인지 아닌지 체크하고 데이터를 넘겨줄지 결정하는 것 같다.
mMvvmSimpleViewModel.someLiveData.observe(viewLifecycleOwner) { binding.tvMvvmsimpleNumber.text = it.toString() }
4. viewLifeCycleOwner란?
Fragment에는 2가지 Lifecycle이 존재한다. LifecycleOwner와 viewLifecycleOwner다.
4-1) LifecycleOwner
fragment 자체의 생명주기를 가지고 있는 class로 onAttach() ~ onDestroy()의 생명주기를 갖고 있다.
mMvvmSimpleViewModel.someLiveData.observe(this) { binding.tvMvvmsimpleNumber.text = it.toString() }
4-2) viewLifecycleOwner
Fragment를 사용하면 onCreateView() 함수가 호출 될 때, view를 생성하고, onViewCreated() 함수에서 이미 생성된 view를 사용한다. viewLifeCycleOwner는 이때 생성된 view의 lifecycle을 의미한다.
그래서 onCreateView ~ onDestroyView 에서의 lifecycle을 가진다.
mMvvmSimpleViewModel.someLiveData.observe(viewLifecycleOwner) { binding.tvMvvmsimpleNumber.text = it.toString() }
Activity의 경우 onDestroy가 호출되지 않는 상황에서 onCreate가 호출 될 일이 없다.
그러나 fragment는 activity와 다르게 onDestroy가 호출되지 않은 상태에서 onCreateView가 여러번 호출 될 수 있다.
예를 들어서 BottomNavigation 사용시 fragment끼리 전환될때 onDestroyView까지만 호출되고 onDestory는 호출되지 않는다.
이럴 경우 다른 fragment에서 사용되었던 LiveData가 그대로 남아있어서, 메모리 누수를 초래하게 될수도 있고, LiveData에 복수의 Observer가 호출되는 현상이 발생할 수도 있다. 그래서 fragment 내부에서 viewLifecycleOwner를 사용하는 것을 권장한다.
'안드로이드 학습 > Android 기술면접 대비' 카테고리의 다른 글
안드로이드 앱 아키텍처 (App Architecture) (0) 2024.10.17 AAC - ViewModel (0) 2024.10.07 안드로이드 비동기 처리 2-3 (Operators : 연산자들) (0) 2024.08.29 안드로이드 비동기 처리 2-2 (RxJava 버전 및 5가지 Base classes) (0) 2024.08.29 안드로이드 Context (0) 2024.08.22