Home > database >  How could i run my logic code inside composable function just 1 time?
How could i run my logic code inside composable function just 1 time?

Time:09-30

I'm doing my test project using ViewModel and ComposeView.

My architecture include: one Activity and multi ComposeView, using navigation like this:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MainView()
        }
    }
}
@Composable
fun MainView() {
    TestComposeTheme {
        val navController = rememberNavController()
        Surface(color = MaterialTheme.colors.background) {
            NavHost(
                navController = navController,
                startDestination = KYCScreen.getName(),
            ) {
                navigation(startDestination = KYCScreen.Preload.name, route = KYCScreen.getName()) {
                    composable(KYCScreen.Preload.name) { PreloadView(navHostController = navController) }
                    composable(KYCScreen.StartKYC.name) { StartView(navHostController = navController) }
                    composable(KYCScreen.Login.name) { LoginView(navHostController = navController) }
                }
                navigation(startDestination = HomeScreen.Home.name, route = HomeScreen.getName()) {
                    composable(HomeScreen.Home.name) { HomeView(navHostController = navController) }
                }
            }
        }
    }
}

The problem happens when I include logic that executes when a Composable function is executed, my logic code was looped many times. Here my code:

@Composable
fun PreloadView(navHostController: NavHostController) {
    val preloadViewModel: PreloadViewModel = viewModel()
    preloadViewModel.getSyncData()
    val syncState by preloadViewModel.uiStateSync.observeAsState()
    syncState?.let { PreloadContent(navHostController = navHostController, it) }
}

@Composable
fun PreloadContent(navHostController: NavHostController, uiState: UiState<SyncResponse>) {
    when (uiState.state) {
        RequestState.SUCCESS -> {
            navHostController.navigate(KYCScreen.StartKYC.name)
        }
        RequestState.FAIL -> {
            Box(
                contentAlignment = Alignment.Center,
                modifier = Modifier
                    .fillMaxHeight()
                    .fillMaxWidth()
            ) {
                Text(text = "Error", color = Color.Black)
            }
        }
        RequestState.NON -> {

        }
    }
}

Anyone have a solution to help me with that architecture?

CodePudding user response:

Your composable function should be side-effects free.

If you want to run something just once. You can do something like the following

 LaunchedEffect(Unit){
     preloadViewModel.getSyncData()
 }

or in your case, if it is mandatory to Sync Data when ViewModel initializes you can call this function in the init block inside of your ViewModel.

Check the official doc https://developer.android.com/jetpack/compose/side-effects

  • Related