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

Jetpack Compose Hilt预览报错ViewModels creation is not supported in Preview如何解决

问题解决:Jetpack Compose预览使用Hilt ViewModel报错

错误原因

你遇到的报错:

java.lang.IllegalStateException: ViewModels creation is not supported in Preview

根本原因是 Compose预览环境不支持Hilt依赖注入框架的ViewModel创建逻辑,hiltViewModel()方法依赖Hilt生成的注入组件,预览环境没有初始化这些组件,因此直接调用会抛出异常。


解决方案

方案1:拆分状态托管层与UI渲染层(最优实践)

该方案符合Compose单向数据流设计规范,彻底解决预览依赖注入问题,同时方便后续单元测试。

步骤1:改造原页面组件,拆分无状态UI实现

@ExperimentalMaterialApi
@Composable
fun AccountListScreen(
    navController: NavController,
    viewModel: AccountListViewModel = hiltViewModel()
) {
    // 从ViewModel中读取所需状态
    val accountList by viewModel.accountList.collectAsStateWithLifecycle()
    val isLoading by viewModel.isLoading.collectAsStateWithLifecycle()
    
    // 调用无状态UI实现,传入状态和事件回调
    AccountListScreenContent(
        accountList = accountList,
        isLoading = isLoading,
        onAccountClick = { accountId ->
            navController.navigate("account/detail/$accountId")
        },
        onRefresh = viewModel::refreshAccountList
    )
}

/**
 * 无状态UI实现,仅负责根据传入的状态渲染界面,所有交互通过回调抛出
 */
@ExperimentalMaterialApi
@Composable
private fun AccountListScreenContent(
    accountList: List<Account>,
    isLoading: Boolean,
    onAccountClick: (String) -> Unit,
    onRefresh: () -> Unit
) {
    // 把原来AccountListScreen里的所有UI渲染逻辑移到这里
}

步骤2:预览时直接调用无状态UI,传入模拟数据

@ExperimentalMaterialApi
@Preview(showBackground = true, backgroundColor = 0xFFFFFF, showSystemUi = true)
@Composable
fun AccountListScreenPreview() {
    // 直接传入模拟的测试数据即可,不需要创建ViewModel
    AccountListScreenContent(
        accountList = listOf(
            Account(id = "1", name = "测试账户1", balance = 100.0),
            Account(id = "2", name = "测试账户2", balance = 200.0)
        ),
        isLoading = false,
        onAccountClick = {},
        onRefresh = {}
    )
}

方案2:手动构造ViewModel模拟实例(适配不想拆分组件的场景)

如果暂时不想拆分组件,可以手动创建ViewModel的模拟实例,直接传给页面组件,不使用hiltViewModel()获取。

@ExperimentalMaterialApi
@Preview(showBackground = true, backgroundColor = 0xFFFFFF, showSystemUi = true)
@Composable
fun AccountListScreenPreview() {
    // 手动构造模拟的ViewModel,依赖的Repository等也用模拟实现
    val mockRepository = MockAccountRepository()
    val previewViewModel = AccountListViewModel(mockRepository)
    
    AccountListScreen(
        navController = rememberNavController(),
        viewModel = previewViewModel
    )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 01:54:02