1 year ago

#310425

test-img

wonpyohong

Compose navigation lose state after pop screen (initial composition)

I am using compose navigation with single activity and no fragments.

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MobileComposePlaygroundTheme {
                Surface(color = MaterialTheme.colors.background) {
                    val navController = rememberNavController()
                    NavHost(navController, startDestination = "main") {
                        composable("main") { MainScreen(navController) }
                        composable("helloScreen") { HelloScreen() }
                    }
                }
            }
        }
    }
}

@Composable
private fun MainScreen(navController: NavHostController) {
    val count = remember {
        Log.d("TAG", "inner remember, that is, initialized")
        mutableStateOf(0)
    }

    LaunchedEffect("fixedKey") {
        Log.d("TAG", "inner LaunchedEffect, that is, initialized")
    }

    Column {
        Spacer(modifier = Modifier.height(16.dp))
        Button(
            onClick = {
                count.value++
                Log.d("TAG", "count: ${count.value}")
            },
            modifier = Modifier.padding(8.dp)
        ) {
            Text(text = "Increase Count ${count.value}")
        }
        Button(
            onClick = { navController.navigate("helloScreen") },
            modifier = Modifier.padding(8.dp)
        ) {
            Text(text = "Go To HelloScreen")
        }
    }
}

@Composable
fun HelloScreen() {
    Log.d("TAG", "HelloScreen")
    Text("Hello Screen")
}

enter image description here

MainScreen -> HelloScreen -> back button -> MainScreen

After pop HelloScreen by back button, MainScreen restart composition from scratch. That is, not recomposition but initial composition. So remember and LaunchedEffect is recalculated.

I got rememberSaveable for maintaining states on this popping upper screen case. However how can I prevent re-execute LaunchedEffect? In addition, docs saying rememberSavable makes value to survive on configuration change but this is not the exact case.

I expected that LowerScreen is just hidden when UpperScreen is pushed, and LowerScreen reveal again when UpperScreen is popped, like old Android's onPause(), onResume(), etc. In Compose, is this not recommended?

ps. Lifecycle of Composable is not tied with ViewModel but with Activity It needs more care about initialization of ViewModel Why Compose team design like this? Can you recommend good architecture sample code?

android

android-jetpack-compose

android-lifecycle

jetpack-compose-navigation

0 Answers

Your Answer

Accepted video resources