Compose - NavHost 多次重组

LMa*_*ker 12 android android-jetpack-navigation android-jetpack-compose jetpack-compose-navigation compose-recomposition

在 Navhost 导航期间,我发现可组合屏幕多次重新组合。因此,我的 ViewModel 也多次调用 API 数据源。

@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)
    }
}
Run Code Online (Sandbox Code Playgroud)

有办法处理吗?我的意思是,我知道 Android Compose 就是这样工作的。但是,如何处理导航屏幕内的 API 调用?

编辑

问题出在 Koin 本身。新版本已经到来,现在可以正常工作了。

cj1*_*098 3

如果您担心重组会导致多次网络调用,那么您始终可以确保每个可组合生命周期仅使用 LaunchedEffect 调用 viewModel 一次。

因此,一种方法是这样的:

LaunchedEffect(Unit) {
    viewModel.getRepositories()
}
Run Code Online (Sandbox Code Playgroud)

只要传递给 LaunchedEffect 的密钥不改变,它就不会重新组合。因此,只要可组合项处于活动状态,使用 Unit 就只会运行一次。

每次导航到该屏幕时,您是否都会重新创建 viewModel?如果是这样,可能值得考虑将网络调用放在块之外的另一个地方init,并使用LaunchedEffect上面的方法或进行创建,这样您就不会在每次导航时重新创建 viewModel。无论哪种方式最适合您的用例。

  • 嘿,“LaunchedEffect(Unit)”在这里不起作用。换屏时仍多次调用API (4认同)