Bookmark profile

안드로이드 컴포즈에서 뷰 모델을 사용하다 보면, 여러 화면에서 상태를 공유해야하는 경우가 있다.

이전에는 아무것도 몰라서 ViewModel을 MainActivity에서 만들어주, 네비게이션에 원하는 화면에 도달할 때까지 계속 전달하였다.

아니 이건… 리액트에서 봤던 프롭스 드릴링!!

처참했다.

하지만, 방법은 있었다! 바로 compositionLocal 이라는 기능이다!

// CompositionLocals.kt
val LocalMainViewModel = compositionLocalOf<MainViewModel> { 
    error("MainViewModel not provided") 
}

이처럼 특정 파일에 공유하고싶은 뷰 모델 객체를 하나 선언해 주고, 타입과 compositionLocalOf 함수를 사용하여 객체를 생성해준다.

이어서 CompositionLocalProvider를 통해서 네비게이션을 감싸준 다음, 생성자에 넣을 파라미터로 위에서 만든 공유 가능한 뷰 모델 타입에 원하는 뷰 모델을 생성해서 넣어준다!

@AndroidEntryPoint
class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            val mainViewModel: MainViewModel = hiltViewModel()

            CompositionLocalProvider(
                LocalMainViewModel provides mainViewModel,
            ) {
                MyApp()
            }
        }
    }

}

그리고 화면에서 사용할 때에는, 다음과 같은 방식으로 사용할 수 있다.

@Composable
fun HomeScreen(navController: NavHostController) {
    val mainViewModel = LocalMainViewModel.current
}

놀랍다! 이렇게 간단한거였다니!!

두개 이상의 화면에서 공유할 필요가 있는 원격 뷰 모델이라면, 예를들면 redux/recoil/mobx와 같이 원격 상태관리가 필요한 뷰모델이라면!

CompositionLocalProvider를 적극 활용해보자!