Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compose - NavHost recomposition multiple times

During navigation from Navhost, I found out that the composable screens are getting recomposition multiple times. Because of it, my ViewModel is calling API data source multiple times too.

@Composable
fun MainView() {
    val scaffoldState = rememberScaffoldState(rememberDrawerState(DrawerValue.Closed))
    val scope = rememberCoroutineScope()
    val navController = rememberNavController()
    Scaffold(
        scaffoldState = scaffoldState,
        topBar = { TopBar(
            toolbarTitle = stringResource(id = R.string.app_name),
            scope = scope,
            scaffoldState = scaffoldState
        ) },
        drawerContent = {
           DrawerView(scope = scope, scaffoldState = scaffoldState, navController = navController)
        },
    ) {
        NavGraph(navController = navController)
    }
}

@Composable
fun NavGraph(navController: NavHostController) {
    NavHost(navController, startDestination = NavDrawerItem.Repositories.route) {
        composable(NavDrawerItem.Repositories.route) {
            RepoListView(getViewModel())
        }

        composable(NavDrawerItem.EmojiList.route) {
            EmojiListView(getViewModel())
        }
    }
} 

class RepoListViewModel(
    private val repositoriesUseCase: GetRepositoriesUseCase
): ViewModel() {
    
    init {
        getRepositories()
    }

@Composable
fun RepoListView(viewModel: RepoListViewModel) {
    AppTheme {
        RepoListContent(viewModel)
    }
}

Is there a way to handle it? I mean, I know it's how Android Compose works. But, How can I handle an API call inside a navigation screen?

EDIT

The problem was Koin itself. A new version has come and now its working properly.

like image 358
LMaker Avatar asked Feb 14 '26 02:02

LMaker


1 Answers

If you're worried about recomposition being the cause of your multiple network calls, you could always make sure that you're only calling into your viewModel once per composable lifecycle with a LaunchedEffect.

So, one approach would be something like:

LaunchedEffect(Unit) {
    viewModel.getRepositories()
}

as long as your key you pass into LaunchedEffect doesn't change it won't recompose. So using Unit will only run this once as long as the composable is alive.

Are you re-creating your viewModel every time you're navigating to that screen? If so, it might be worth looking into putting your network call in another place besides the init block and using the LaunchedEffect approach above OR making it so you're not re-creating your viewModel on every navigation. Whatever fits your use-case best.

like image 133
cj1098 Avatar answered Feb 16 '26 18:02

cj1098



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!