You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Composable函数中正确创建ViewModel以避免代码重复执行问题

问题原因

你观察到的两次日志打印是Jetpack Compose的正常重组机制导致的:hiltViewModel() 是带副作用的Composable调用,首次执行时会完成ViewModel的实例化,这个过程会触发当前ItemDetailsScreen的二次重组,因此顶层的Log语句会执行两次。当你注释掉ViewModel参数后,没有触发二次重组的来源,所以只会执行一次初始重组。

Compose本身设计就是可以按需多次执行重组,只要保证重组逻辑是幂等的就不会有问题,但你需要把带副作用的逻辑和UI渲染逻辑拆分。

解决方案

如果要让日志、数据请求这类仅需执行一次的逻辑不随重组重复运行,使用LaunchedEffect包裹即可,绑定固定Key(比如当前页面的itemId),只要Key不变,内部逻辑就只会在页面首次进入时执行一次:

fun ItemDetailsScreen(
    navController: NavController,
    itemId: String,
    viewModel: ItemDetailsViewModel = hiltViewModel()
) {
    // 绑定itemId作为Key,仅当itemId变化时才重新执行内部代码
    LaunchedEffect(key1 = itemId) {
        Log.d(TAG, itemId)
        // 页面数据请求逻辑也放在这里,避免重复请求
        viewModel.getItem(itemId)
    }
    
    // 原有UI渲染逻辑保持不变
}

如果有其他需要和重组生命周期解绑的逻辑,也可以根据场景选择SideEffect、DisposableEffect等 Compose 副作用API处理,不要直接写在Composable的顶层作用域。


内容的提问来源于stack exchange,提问作者Always Learner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 17:36:02