Search code examples
androidandroid-jetpack-composeandroid-architecture-navigation

(Jetpackcompose) onCreate method runs multiple times


I'm using Navigation Components in jetpack compose. When I navigate to other,onCreate was launch 5,6 times.

It's my application log when I start the app and navigate to other routes ->

2021-09-25 16:40:41.486 28201-28201/ D/HomeScreenKt$HomeScreen: ON_START
2021-09-25 16:40:41.486 28201-28201/ D/HomeScreenKt$HomeScreen: ON_RESUME
2021-09-25 16:40:41.486 28201-28201/ D/HomeScreenKt$HomeScreen: ON_START
2021-09-25 16:40:41.486 28201-28201/  D/HomeScreenKt$HomeScreen: ON_RESUME
2021-09-25 16:40:41.486 28201-28201/ D/HomeScreenKt$HomeScreen: ON_START
2021-09-25 16:40:41.486 28201-28201/ D/HomeScreenKt$HomeScreen: ON_RESUME
2021-09-25 16:40:41.487 28201-28201/ D/HomeScreenKt$HomeScreen: ON_START
2021-09-25 16:40:41.487 28201-28201/ D/HomeScreenKt$HomeScreen: ON_RESUME
2021-09-25 16:40:41.488 28201-28201/ D/HomeScreenKt$HomeScreen: ON_START
2021-09-25 16:40:41.488 28201-28201/ D/HomeScreenKt$HomeScreen: ON_RESUME
2021-09-25 16:40:41.509 28201-28201/ D/HomeScreenKt$HomeScreen: ON_CREATE
2021-09-25 16:40:41.510 28201-28201/ D/HomeScreenKt$HomeScreen: ON_START
2021-09-25 16:40:41.511 28201-28201/ D/HomeScreenKt$HomeScreen: ON_RESUME
2021-09-25 16:40:41.637 28201-28201/ D/HomeScreenKt$HomeScreen: ON_CREATE
2021-09-25 16:40:41.638 28201-28201/ D/HomeScreenKt$HomeScreen: ON_START
2021-09-25 16:40:41.638 28201-28201/ D/HomeScreenKt$HomeScreen: ON_RESUME
2021-09-25 16:40:41.926 28201-28201/ D/HomeScreenKt$HomeScreen: ON_CREATE
2021-09-25 16:40:41.926 28201-28201/ D/HomeScreenKt$HomeScreen: ON_START
2021-09-25 16:40:41.928 28201-28201/ D/HomeScreenKt$HomeScreen: ON_RESUME
2021-09-25 16:40:41.944 28201-28201/ D/HomeScreenKt$HomeScreen: ON_CREATE
2021-09-25 16:40:41.944 28201-28201/ D/HomeScreenKt$HomeScreen: ON_START
2021-09-25 16:40:41.947 28201-28201/ D/HomeScreenKt$HomeScreen: ON_RESUME

It's an application section that was I config navigation components ->

   AppTheme{
        val appStateHolder = rememberAppStateHolder()
        Scaffold(
            bottomBar ={
                if (appStateHolder.shouldShowBottomBar){
                    BottomNav(
                        navigateToRoute = appStateHolder::navigateToBottomBarRoute
                    )
                }
            },
            scaffoldState = appStateHolder.scaffoldState
        ) {
            NavHost(
                navController = appStateHolder.navController,
                startDestination = Constants.Navigation.HOME_SCREEN
            ) {
                composable(Constants.Navigation.HOME_SCREEN) { HomeScreen(viewModel = hiltViewModel()) }
                composable(Constants.Navigation.MAP_SCREEN) { MapScreen(viewModel = hiltViewModel()) }
                composable(Constants.Navigation.LOCATION_SCREEN) {  }
                composable(Constants.Navigation.CHART_SCREEN) {  }
                composable(Constants.Navigation.SEARCH_SCREEN) {  }
            }
        }
   }

HomeScreen ->

fun HomeScreen(viewModel: HomeViewModel) {
    LocalLifecycleOwner.current.lifecycle.addObserver(object : LifecycleEventObserver {
        override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
            Timber.d(event.name)
        }
}

Solution

  • Side-effects

    A side-effect is a change to the state of the app that happens outside the scope of a composable function. Due to composables' lifecycle and properties such as unpredictable recompositions, executing recompositions of composables in different orders, or recompositions that can be discarded, composables should ideally be side-effect free.

    read more


    Adding observable in Compose functions should be used inside a DisposableEffect block and also should be properly removed in onDispose lambda.

    Example:

    @Composable
    fun HomeScreen() {
        val lifecycleOwner = LocalLifecycleOwner.current
    
        DisposableEffect(this) {
            val observer = LifecycleEventObserver { source, event -> Timber.d(event.name) }
            lifecycleOwner.lifecycle.addObserver(observer)
    
            onDispose {
                lifecycleOwner.lifecycle.removeObserver(observer)
            }
        }
    }
    

    The reason is that recompositions could happen many times. In your case, .addObserver method was called 5-6 times during the recomposition.