이 포스팅에서는 AAC ViewModel의 생성과 파괴에 대해 알아볼 것이다.
ViewModel에 대한 자세한 설명은 공식 문서에서 확인할 수 있다.
Activity
에서 ViewModel
을 가져올 때 activity-ktx artifact
에 있는 방식 사용.
Activity
가 파괴되기 전까지는 동일한 ViewModel
인스턴스를 보장하는 데 코드를 통해 확인해보자.
by viewModels()의 내부 코드를 확인해보면 아래 클래스를 return 하고 있다.
코드를 살펴보면 cache된 ViewModel
이 없을 경우 ViewModelProvider
의 get()
함수를 통해 ViewModel
을 가져와 반환하고 있을 경우 cache된 ViewModel
을 반환한다.
Activity
에서 ViewModel
을 멤버 변수로 가지고 있다면 최초에는 ViewModelProvider
를 통해 가져오고 그 이후에는 cache된 ViewModel
을 반환할 것이다.
하지만 변수가 onCreate()
안에서 선언되어 있다면 onCreate()
가 호출될 때마다 cache된 값이 존재하지 않아 ViewModelProvider
의 get()
함수를 통해 가져올 것이다.
mViewModelStore
에서 일치하는 ViewModel
을 가져온 뒤 인스턴스를 비교해 일치하면 반환하고 아닐 경우 새로 생성한 뒤 mViewModelStore
에 저장한다.
ViewModel
을 Map
형태로 저장하고 있음을 알 수 있다. get()
, put()
메서드로 관리하며 clear()
메서드는 Map
에 저장된 모든 ViewModel
의 clear()
메서드가 호출한 뒤 Map
을 비워주는 작업을 하고 있다.
ViewModelProvider
에서 사용되는mViewModelStore
는AppCompatActivity
부모인ComponentActivity
에 있는ViewModelStore
를 사용한다.
Activity
에서 ViewModel
을 가져올 때 최초에는 생성한 뒤 ViewModelStore
에 저장한다. 그다음부터는 ViewModelStore
에서 일치하는 ViewModel
을 반환해 주기 때문에 Acitivty
가 파괴되지 않는 이상 동일한 인스턴스의 ViewModel
을 보장한다.
이번엔 ViewModel
이 파괴되는 시점을 확인해보자.
ViewModel
의 범위는 ViewModel
을 가져올 때 ViewModelProvider
에 전달되는 Lifecycle
로 지정된다. 예를 들면 Activity
에서 생성할 경우 Activity
가 끝날 때까지 메모리에 남아있게 된다.
다음은 ComponentActivity
에 포함된 코드이다.
LifecycleEventObserver
을 통해 LifeCycle
을 관찰하며ON_DESTROY
상태일 때 해당 코드가 실행된다.
isChangingConfigurations()
가 false 일 경우에 아까 살펴본 ViewModelStore
의 clear()
메서드가 호출되며 생성된 모든 ViewModel
이 제거된다.
반대로 isChangingConfigurations()
값이 true 일 경우에는 ViewModel
이 제거되지 않을 것이다.
일부 기기 구성은 런타임에 변경될 수 있다.(기기의 화면 회전이나, 언어 설정 등의 이유)
이러한 변경이 일어나는 경우 Android는 실행 중인 Activity
를 다시 시작한다. (onDestroy()
가 호출되고, 그다음에 onCreate()
가 호출됨)
isChangingConfigurations()
조건이 걸려있는 이유는 Configuration change가 발생하여 Activity
의 onDestroy()
가 호출되어도 ViewModel
의 인스턴스를 유지하기 위한 처리이다.
ON_DESTROY
시점에 Configuration change가 아닐 경우 ViewModelStore
의 clear()
메서드가 호출되어 Acitivty
에서 생성한 ViewModel
이 모두 제거되는 것을 알 수 있었다.
반대로 Configuration change가 변경됐을 때에는 Activity
의 onDestroy()
가 호출되고, 그다음에 onCreate()
가 호출되기 때문에 ViewModel
인스턴스 유지를 위해 ViewModelStore
의 clear()
는 실행되지 않는다.