이번 글에서는 MVVM 패턴에서 빠질 수 없는 요소인 ViewModel에 대해서 공부해 본 걸 정리할까(?) 합니다.
자세한 내용과 코드는 공식문서에 있으므로, 공식문서를 참고하시면 될 것 같습니다..
(제가 편한대로 정리하기 때문)
ViewModel이란?
액티비티와 프래그먼트와 같은 UI 컨트롤러의 로직에서 데이터를 다루는 로직을 분리하기 위해 등장한 Android JetPack 라이브러리이다.
두 가지를 분리해야 하는 이유
UI 컨트롤러(Activity, Fragment)의 목적
- 데이터를 표시해 주거나, 사용자가 어떤 작업을 했을 때 반응을 보여주거나 , 권한 요청과 같은 OS커뮤니케이션을 처리하는 것이 UI 컨트롤러의 목적이다.
- 따라서 UI 컨트롤러에서 데이터를 다루는 로직을 책임지게 되면 많은 유지보수가 필요한 비동기 호출과 같은 작업들을 해야 한다.
- 쉽게 말하면 UI 컨트롤러에 과도한 책임이 생기게 된다.라고 생각하면 편하겠다.
데이터 손실 방지
- UI 컨트롤러에서는 생명주기에 따라 앱이 활동 중에 제거될 때마다 데이터를 저장시키고, 다시 생성될 때마다 데이터들을 다시 불러와야 한다.
- 데이터를 복원하기 위해 onSaveInstanceState() 메서드를 사용하는 방법은 작은 용량의 데이터에만 적합하고 데이터가 커지게 되면 적합하지 않다.
ViewModel의 생명 주기
Activity의 생명주기와 상관없이 생명주기가 살아있다면 데이터가 쭉 유지되고,
그렇게 되면 데이터의 손실을 방지
할 수 있습니다.
그래서 ViewModel은 Activity의 생명 주기보다 긴 수명을 가지는 생명주기를 갖게 됩니다.
ViewModel의 생명주기 범위는 ViewModel을 가져올 때 ViewModelProvider에 의해 결정됩니다.
위 그림과 같이 Activity가 생성되고, 다양한 생명주기를 갖게 되지만 그때 동안, ViewModel은 종료되지 않고 쭉 살아있게 됩니다. 화면회전과 같은 상황에서 Activity가 재생성되더라도, ViewModel을 사용하면 데이터를 유지
할 수 있습니다.
-> ViewModel을 사용하는 장점 중 하나입니다.
ViewModel이 메모리에서 사리지는 시기
- Activity가 onDestory()를 호출하는 경우
- Fragement의 경우 분리된 경우
- 탐색 항목의 경우 백 스택에서 삭제된 경우
위와 같은 경우에서 onClear()를 호출해서 내부 데이터를 초기화하고 삭제합니다.
ViewModel 프로세스 요청 과정
- 사용자가 ViewModelProvider를 통해 ViewModel 인스턴스를 요청
- ViewModelProvider 내부에서는 ViewModelStoreOwner를 참조하여 ViewModelStore를 가져옴.
- ViewModelStore에게 이미 생성된 ViewModel 인스턴스를 요청
- 만약 ViewModelStore가 적합한 ViewModel 인스턴스를 가지고 있지 않다면,
ViewModelProvider.Factory를 통해 ViewModel 인스턴스를 생성 - 생성한 ViewModel 인스턴스를 ViewModelStore에 저장하고, 만들어진 ViewModel 인스턴스를 클라이언트(요청자)에게 반환
말이 굉장히 어렵죠. 네 저도 좀 어렵네요
구성요소를 뜯어보겠습니다.
ViewModelProvider
ViewModelProvider (ViewModelStoreOwner owner, ViewModelProvider.Factory factory)
- 첫 번째 매개변수는 ViewModelStoreOwner인데 ViewModelStore의 정보를 가지고 옵니다.
- ViewModelStore는 ViewModel이 어떤 Activity와 연관되어 있는지에 대한 정보를 가지고 있습니다.
자신의 데이터가 유지되어야 할 View(Activity, Fragment)에 정보가 있습니다.
- ViewModelStore는 ViewModel이 어떤 Activity와 연관되어 있는지에 대한 정보를 가지고 있습니다.
- 두 번째 매개변수는 ViewModelProvider.Factory로 실직적으로 ViewModel 인스턴스를 생성하는 역할을 하는 Factory가 들어갑니다.
- ViewModel은 Factory패턴으로 구현된다!!
ViewModelStoreOwner
ViewModelStoreOwner는 ViewModelStore를 관리하는 scope입니다.
AppCompatActivity를 사용하고 있다면 별도로 ViewModelStoreOwner를 구현할 필요는 없습니다.
(Fragment도 마찬가지)
ViewModelStore
ViewModelStore는 HashMap(key : String, value : ViewModel) 구조로 ViewModel을 관리하는 클래스입니다.
ViewModelStore는 구성 요소의 변경 속에서도 유지되는 인스턴스입니다.
만약 ViewModelStore의 Owner(액티비티, 프래그먼트)가 변경되더라도, owner의 새로운 객체는 여전히 같은 ViewModelStore를 가지고 있습니다. 그렇기에 액티비티나 프래그먼트에 생명주기가 완전히 종료되지 않는 이상 똑같은 ViewModelStore를 가지고 있고, 이 ViewModelStore가 ViewModel을 관리하기에 데이터가 유지되는 것입니다.
ViewModelProvider.Factory
ViewModelProvider안에 선언된 인터페이스로 ViewModel들을 인스턴스화할 수 있습니다.
(자신만의 방식으로 ViewModel 인스턴스를 생성할 수 있다)
ViewModel 사용 시 주의할 점
- ViewModel은 Activity, Fragment, Context를 참조하면 안 된다.
- ViewModel은 액티비티, 프래그먼트보다 긴 생명주기를 가지고 있다.
ViewModel의 생명주기는 위에 구성요소에 종속되지 않습니다. - 액티비티는 계속 종료와 생성을 반복하지만, ViewModel은 onClear()가 호출되지 않는 이상 유지되는데 계속 종료와 생성되는 액티비티를 참조할 필요가 없습니다.
- 참조할 경우 메모리 릭이 발생할 수 있다!
- ViewModel은 액티비티, 프래그먼트보다 긴 생명주기를 가지고 있다.
- 액티비티/프래그먼트에 하나의 ViewModel을 사용하는 것을 권장한다.
- 복잡도가 높기에 하나의 ViewModel의 여러 LiveData를 다루는 구조가 효과적인가 효율적이다.
요약
- ViewModel은 UI와 관련된 데이터 모델과 모델을 처리하는 로직을
분리
하기 위해서 사용된다.- 액티비티, 프래그먼트를 더욱 가볍게 만들기 위해서 UI와 데이터를 분리 -> 유지보수가 쉬움.
- UI는 UI만 담당, 데이터는 데이터만 담당
- ViewModel은 액티비티가 생성되고 종료될 때마다 계속해서 데이터를 들고 오는 방식을 해결해 준다.
- ViewModel은 액티비티의 생명주기에 종속되지 않기에, onClear()가 호출되지 않는 이상 데이터를
계속 유지하고 있다.
- ViewModel은 액티비티의 생명주기에 종속되지 않기에, onClear()가 호출되지 않는 이상 데이터를
느낀 점
- 공식문서에는 굉장히 자세하게 나와있다.
- 인자하나하나가 어떤 의미인지 더욱 자세히 알 필요가 있는 것 같음.
- 점점 공부하면 할수록 클린 아키텍처가 중요하다는 것을 깨닫는 중
- 어렵다.
'Skils > Android' 카테고리의 다른 글
[Android] - Context (0) | 2023.02.22 |
---|---|
[Android] - Live Data (0) | 2023.02.12 |
[Android] - 안드로이드 설계 패턴(MVP) (0) | 2023.02.05 |
[Android] - 안드로이드 설계 패턴 (MVC) (0) | 2023.02.04 |
[Android] - Clean Architecture (0) | 2023.01.30 |