简体   繁体   中英

Avoid API call in composable when navigating back to it

What I'm trying to do is avoid to make the api call that is called in a composable when press back from another composable.

I have composable DetailScreen that makes the api call and get some data and then navigate to composable EpisodeScreen, here is the thing, when I press back it's navigate back to composable DetailScreen but it makes de api call again and that is what I'm tryin to avoid.

Here is my Composable DetailScreen:

@Composable
fun DetailScreen(
    viewModel: DetailViewModel = hiltViewModel(),
    id: Int,
    name: String,
    picture: String,
    onClickBack: () -> Unit,
    onClickEpisode: (Int) -> Unit
) {

   
    LaunchedEffect(key1 = Unit) {
        //this is the line I'm trying to avoid when navigate back from composable EpisodeScreen
        viewModel.getCharacterDetail(id)
    }

...

Here is the navigation to composable EpisodeScreen:

private fun NavGraphBuilder.addDetailGraph(navController: NavHostController) {
    composable(
        route = Screen.Detail.route,
        arguments = listOf(
            navArgument("id") { type = NavType.IntType },
            navArgument("name") { type = NavType.StringType },
            navArgument("image") { type = NavType.StringType }
        )
    ) { backStackEntry ->
        val id = backStackEntry.arguments?.getInt("id") ?: 0
        val name = backStackEntry.arguments?.getString("name") ?: ""
        val image = backStackEntry.arguments?.getString("image") ?: ""

        DetailScreen(
            id = id,
            picture = image,
            name = name,
            onClickBack = {
                navController.popBackStack()
            },
            onClickEpisode = { episodeId ->
                navController.navigate(
                    Screen.Episode.createRoute(id = episodeId)
                ) 
            }
        )
    }
}

I tried to keep a state with remember and remembersaveable and put it as parameter in LaunchEffect() but nothing and I can´t find info or I can see it

Can anyone help me with this?? thanks in advance:)

Your DetailViewModel instance will still be alive when you navigate to the Episode screen, so you can put some logic there. You can do one of the following:

  • Create a boolean in your ViewModel, initially set to false . Inside the setCharacter function, check the value of this variable. If it's true just return otherwise change it to true and execute rest of the code. Or if you already have a variable in ViewModel which is initialized inside setCharacter , you can use that instead of that boolean.

  • Another option is to call in the setCharacter function inside the init block of the view model. And you can get the id from the SavedStateHandle that you can inject in the view model.

in viewmodel add following variable

var isLoaded = true

and in launchedEffect

    @Composable
    fun DetailScreen(
        viewModel: DetailViewModel = hiltViewModel(),
        id: Int,
        name: String,
        picture: String,
        onClickBack: () -> Unit,
        onClickEpisode: (Int) -> Unit
    ) {
    
      
        LaunchedEffect(key1 = Unit) {
            // add this check
            if (viewModel.isLoaded) {
            viewModel.getCharacterDetail(id) }
}

when navigating to detail screen and then navigate back -> recomposition take place and code inside launchedEffect will run again. To remove this add above checking.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM