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

Jetpack Compose中注入ViewModel导致UI预览渲染失败问题

Jetpack Compose预览报错:KoinApplication未启动的原因与解决方法

我使用Jetpack Compose开发项目,采用Koin实现依赖注入。在@Composable函数中注入ViewModel并观察数据时,UI预览无法正常渲染,抛出以下异常:

java.lang.IllegalStateException: KoinApplication has not been started
at org.koin.core.context.GlobalContext.get(GlobalContext.kt:36)
at org.koin.compose.KoinApplicationKt.getKoinContext(KoinApplication.kt:52)
at org.koin.compose.KoinApplicationKt.access$getKoinContext(KoinApplication.kt:1)
at org.koin.compose.KoinApplicationKt.getKoinScope(KoinApplication.kt:86)

我已在Application类中完成Koin初始化,并在Manifest中配置了该类:

class MainApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        startKoin {
            androidLogger()
            androidContext(this@MainApplication)
            modules(ApiModule)
            modules(appModule)
        }
    }
}

Manifest配置:

<application
    android:allowBackup="true"
    android:dataExtractionRules="@xml/data_extraction_rules"
    android:fullBackupContent="@xml/backup_rules"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/Theme.ComposeRetrofit"
    android:name=".MainApplication"
    tools:targetApi="31">

Compose代码:

@Preview
@Composable
fun ViewForMainScreen(){
    MainScreen()
}

@Composable
fun getApplianceViewModel(): ApplianceViewModel {
    return koinViewModel()
}

@Composable
fun getAddressViewModel(): AddressViewModel {
    return koinViewModel()
}

@Composable
fun MainScreen(){
    val addressViewModel = getAddressViewModel()
    val address by addressViewModel.addressApiResponse.observeAsState(initial = null)

    Column(
        modifier = Modifier
            .fillMaxWidth()
            .height(100.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Button(
            onClick = { addressViewModel.callAddressApi() },
            modifier = Modifier
                .fillMaxWidth()
                .height(40.dp)
                .padding(start = 40.dp, end = 40.dp)
        ) {
            Text(text = address?.mailBox ?: "Country")
        }
        Spacer(modifier = Modifier.height(20.dp))
        Text(
            text = address?.fullAddress ?: "Full Address",
            modifier = Modifier.padding(start = 40.dp, end = 40.dp)
        )
    }
}

问题原因

  • Compose预览的运行环境是独立沙箱,不会启动你配置的MainApplication类,因此不会执行其中的Koin初始化逻辑,导致预览时Koin全局上下文未创建。
  • 预览系统仅加载Compose UI组件本身,不会触发Application的生命周期回调。

解决方法

方法一:在预览函数中手动初始化Koin

修改预览函数,用KoinApplication包裹待预览的Compose内容,手动初始化Koin模块:

@Preview
@Composable
fun ViewForMainScreen(){
    KoinApplication(application = {
        androidLogger()
        androidContext(LocalContext.current)
        modules(ApiModule, appModule)
    }) {
        MainScreen()
    }
}

方法二:使用模拟ViewModel替代依赖注入

为ViewModel创建模拟实现,在预览中直接传入模拟实例,避免依赖Koin:

// 模拟AddressViewModel
class MockAddressViewModel : AddressViewModel() {
    override val addressApiResponse = MutableStateFlow(Address(
        mailBox = "Mock Country",
        fullAddress = "Mock Full Address"
    ))
}

@Preview
@Composable
fun ViewForMainScreen(){
    val mockViewModel = MockAddressViewModel()
    val address by mockViewModel.addressApiResponse.observeAsState()
    
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .height(100.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Button(
            onClick = {},
            modifier = Modifier
                .fillMaxWidth()
                .height(40.dp)
                .padding(start = 40.dp, end = 40.dp)
        ) {
            Text(text = address?.mailBox ?: "Country")
        }
        Spacer(modifier = Modifier.height(20.dp))
        Text(
            text = address?.fullAddress ?: "Full Address",
            modifier = Modifier.padding(start = 40.dp, end = 40.dp)
        )
    }
}

方法三:升级Koin到最新版本

最新版的Koin Compose库已针对预览场景做了优化,升级后可能无需额外配置即可自动处理预览时的Koin上下文初始化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 01:35:37