ViewModel
ViewModel 은 이제는 안드로이드 프로그래밍에 있어서 필수 불가결한 존재가 되었습니다. 특히 MVVM, MVI, MVW 등, 관심사의 철저한 분리가 요구되는 아키텍처에는 꼭 필요합니다. 특정 아키텍처를 적용하지 않더라도, View 가 표시할 상태나 데이터를 위해 ViewModel 이 필요하기도 하고요.
Rx라이브러리를 이용하거나 ViewModel 내에서 특정 리소스를 Observing 하는 경우에는 메모리 릭에 대한 리스크를 관리하기 위해 ViewModel 의 onCleared() 에서 관련 작업 또는 리소스들을 해제해주어야 합니다. 이는 다소 제네럴한 지식이고요.
문득, onCleared() 가 언제, 또 어떻게 호출되는지 궁금해졌습니다.
내부 동작 방식
ViewModel 의 onCleared() 는 그 명칭을 보아 호출의 주체가 되지 않는 함수로 보입니다. 즉, 개발자에 의해 직접 호출되는 것이 아닌, 내부적으로 이미 해당 메서드를 호출하고 있는 소스가 존재한다는 것입니다.
@SuppressWarnings("WeakerAccess")
protected void onCleared() {
}
@MainThread
final void clear() {
mCleared = true;
if (mBagOfTags != null) {
synchronized (mBagOfTags) {
for (Object value : mBagOfTags.values()) {
closeWithRuntimeException(value);
}
}
}
if (mCloseables != null) {
synchronized (mCloseables) {
for (Closeable closeable : mCloseables) {
closeWithRuntimeException(closeable);
}
}
}
onCleared();
}
onCleared() 메서드는 clear() 메서드의 마지막에 호출됩니다. clear() 메서드는 ViewModelStore 클래스의 clear() 메서드에서 호출됩니다.
/**
* Clears internal storage and notifies `ViewModel`s that they are no longer used.
*/
fun clear() {
for (vm in map.values) {
vm.clear()
}
map.clear()
}
다소 간단한 명세의 clear() 메서드는 ComponentActivity 에서, 발생한 Lifecycle Event 가 ON_DESTROY 인 경우 호출됩니다.
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
// Clear out the available context
mContextAwareHelper.clearAvailableContext();
// And clear the ViewModelStore
if (!isChangingConfigurations()) {
getViewModelStore().clear();
}
mReportFullyDrawnExecutor.activityDestroyed();
}
}
});
ComponentActivity 의 기본 생성자에 정의된 코드이며, Lifecycle 을 트래킹하는 익명 클래스를 통해 통지하는 방식으로 구현되어 있습니다. Lifecycle Event 는 ON_DESTROY 이지만 구성 변경이 아닌 경우에만 동작합니다. 즉, ViewModel 은 Activity 의 onDestroy 에 해제됩니다.
포스팅 동기
"왜 UI 데이터의 보존과 핸들링을 위해 ViewModel 을 사용해야 하나요?"
라는 질문을 보게되었고, 쉽게 대답할 수 있는 질문이라고 생각했습니다. 그래서 답변을 생각해보았습니다.
"관심사의 분리를 위해 Activity / Fragment 는 UI 표시를 위한 역할만을 담당하고, 그에 대한 데이터 핸들링은 Activity 나 Fragment 보다 생명주기가 조금 더 긴 ViewModel 에서 담당하는 것이 UI 데이터 처리의 안정적인 방식이기 때문입니다."
제가 참여하고 있는 네이버 부스트캠프의 동료 캠퍼들도 비슷하게 답변을 줬는데요.
그런데 문득, OnDestroy 는 Activity 의 해제를 의미하는데, 그렇다면 ViewModel 을 해제해주는 건 누가 담당하는 걸까? 라는 의문이 들었습니다.
이러한 동기로 이에 관해 정리하고 싶었고, 정리한 결과, 조금은 다르게 답변해야 함을 알 수 있었습니다.
"관심사의 분리를 위해 Activity / Fragment 는 UI 표시를 위한 역할만을 담당하고, 그에 대한 데이터 핸들링은 런타임 중 안드로이드 구성 변경 등에 의해 해제되지 않는 ViewModel 에서 담당하는 것이 UI 데이터 처리의 안정적인 방식이기 때문입니다."
ViewModel 과 관련된 글에 꼭 등장하는 이미지입니다. 이 이미지가 설명하려 하는 바는 ViewModel 은 onCleared() 에 메모리에서 해제된다 인 것 같은데, 이게 하필 Activity Lifecycle 바로 옆에 수직으로 그려져 있어서 '아, ViewModel 은 Activity 보다 조금 더 긴 Lifecycle 을 가지는구나!' 라고 착각하게 된 것 같습니다.
즉, ViewModel 은 Activity 보다 더 긴 Lifecycle 을 가지는 게 아닌, 구성 변경에 의해 해제되지 않는 것일 뿐, Activity 의 onDestory 에 함께 해제된다. 입니다.
'Android > Tech' 카테고리의 다른 글
[Retrofit] Call<T>.enqueue() 와 suspendable 메서드 호출 방식의 차이 (0) | 2023.10.03 |
---|---|
RecyclerView 의 업데이트와 DiffUtil (0) | 2023.09.29 |
@Retention 은 어떻게 동작하는가? (0) | 2023.09.05 |
Kapt, 그리고 KSP (0) | 2023.09.01 |
내부 리소스 접근에 왜 Context 가 필요한 걸까? (0) | 2023.08.21 |