Composable끼리 ViewModel 공유하기

Jetpack Compose에서 지원하는 viewModel을 쓰면, Composable간에 ViewModel이 공유되지 않는다. Compose Navigation을 쓰다가 ViewModel을 서로 공유 받아야 하는 상황이 발생해서 연구한 내용을 작성한다.

기본 viewModel

Compose에서 기본적으로 지원하는 viewModel 함수는 아래와 같이 구현돼 있다.

보면 viewModelStoreOwner 인자로 LocalViewModelStoreOwner를 받는걸 알 수 있다. 그럼 이 부분에 동일한 ViewModelStoreOwner를 넣어주면 되지 않을까? 해서 각각의 Composable끼리 동일한 ViewModelStoreOwner를 얻을 수 있는 방법을 찾아봤다.

동일한 ViewModelStoreOwner

일반적인 안드로이드에서 생각해 보면 Activity-Context를 Activity로 받을 수 있다. 그러면 Composable에서 Context를 받아와 ComponentActivity로 캐스팅 해주면 되지 않을까? 싶음 마음에 아래 코드를 만들어 시도해 보았다.

inline으로 만들어줘야 작동할 줄 알았는데, 의외로 inline 없이 사용해도 해당 Composable이 사용된 Activity가 잘 구해졌다. Compose Navigation은 결국 하나의 ComponentActivity에서 구현되므로, 이 함수를 써서 Navigation Composable들도 각각 같은 Activity를 구할 수 있을 것이다.

composableActivityViewModel

동일한 ViewModelStoreOwner를 구하는건 성공했다. 그럼 위에서 봤던 기본 viewModel 함수의 viewModelStoreOwner 인자로 getActivity() 함수의 값을 넣어주면 각각 Composable에서도 동일한 ViewModel 인스턴스를 가져올 수 있을거 같아 아래와 같은 코드를 만들고 사용해 봤다.

결과는 각각 다른 Composable에서 같은 ViewModel 인스턴스를 사용할 수 있었다.

마무리

composableActivityViewModel를 포함해, 내가 자주 쓰는 Composable 유틸 함수들이 꽤 많이 생겼다. 대부분 직접 구현한거라 이 부분들을 모아둔 라이브러리를 출시해도 될거 같다. 매 프로젝트를 시작할 때 마다 복붙해서 사용하는 것 보다 하나의 라이브러리로 만들어두면 훨씬 편하겠지.

추가로 그냥 시작되는 Activity에서 전역변수로 ViewModel를 선언하고, 각각 Navigation Composable들의 인자로 뷰모델을 받는 방법도 있다. 근데 이건 유지보수에 한계가 있어 비추천하는 방법이다.

iOS 개발자를 꿈꾸는 토스팀 안드로이드 취준생 / github.com/jisungbin

iOS 개발자를 꿈꾸는 토스팀 안드로이드 취준생 / github.com/jisungbin