문제 원인
MVVM 디자인 패턴을 따라서 앱 제작을 하던 중 두 Fragment간 ViewModel의 인스턴스 공유 문제가 발생했다.
private val homeViewModel: HomeViewModel by viewModels()
나는 처음엔 Fragment의 각각에 위 코드를 작성하면 같은 ViewModel을 사용할 것이라고 생각했다. 하지만 by viewModels()를 사용하면 각 Fragment가 고유한 ViewModel 인스턴스를 생성하기 때문에 LiveData가 변경되더라도 Fragment에서 감지하지 못했다. 이는 각각의 Fragment가 서로 다른 ViewModel 인스턴스를 참조하고 있었기 때문이다.
해결 방법
해결 방법은 간단했다.
private val homeViewModel: HomeViewModel by activityViewModels()
ViewModel을 Fragment 범위가 아닌 Activity 범위에서 공유하도록 변경했다. 이를 위해 viewModel() 대신 by activityViewModel()을 사용했다. 이렇게 함으로써, 두 Fragment가 동일한 ViewModel 인스턴스를 참조하게 되었다.
결과
ViewModel을 사용하는 경우, Activity와 Fragment 간의 범위(scope)를 명확히 이해할 필요가 있다.
+ Hilt를 사용한 문제 해결 방법
Hilt와 Navigation 컴포넌트를 함께 사용하면 내가 겪었던 ViewModel 인스턴스 공유 문제를 쉽게 해결할 수 있다고 한다. 화면 간 전환에서 Navigation 컴포넌트와 함께 Hilt를 사용하여 ViewModel을 주입한다는 것이다.
Hilt를 사용하면 ViewModel의 생명 주기를 Activity나 Fragment에 자동으로 맞춰 관리할 수 있다.
Hilt gradle을 설정을 하고, ViewModel을 사용하는 Fragment에 @HiltViewModel 어노테이션을 달아주자. 그리고 아래와 같이 hiltNavGraphViewModels를 사용한다.
private val homeViewModel: HomeViewModel by hiltNavGraphViewModels(R.id.nav_graph)
'Android' 카테고리의 다른 글
[Jetpack Compose] Compose에서의 Statelss/Stateful (2) | 2024.09.06 |
---|---|
[Jetpack Compose] Jetpack Compose의 이해 (0) | 2024.09.06 |
[Android] ViewPager2에 관련된 속성들 (0) | 2024.05.03 |
[Android] String Resources - <string-array>로 깔끔하게 관리하자 (0) | 2024.04.02 |
[Android] ViewPager2에 custom indicator 연결하기 (7) | 2024.03.18 |