KMP中使用Koin时ViewModel返回后未销毁问题求助
解决KMP中Koin ViewModel重复实例问题
问题原因
默认情况下,koinViewModel会绑定到当前的生命周期Scope(如导航条目或组件Scope),页面返回后该Scope未被销毁,导致再次进入时复用旧ViewModel实例。直接使用时间戳作为key无效,因为Scope本身未更新,Koin仍会在同一个Scope中查找对应key的实例。
解决方案
通过创建页面专属的临时Scope,绑定ViewModel到该Scope,页面销毁时关闭Scope,确保ViewModel被回收,每次进入页面都生成新实例。
步骤1:正确声明ViewModel
在Koin模块中,使用viewModel声明(保证ViewModel的生命周期管理):
val appModule = module { viewModel { AddOrEditViewModel(get()) } // 其他依赖声明... }
步骤2:在Compose页面中使用临时Scope
@Composable fun AddOrEditScreen() { // 每次进入页面创建新的专属Scope val screenScope = remember { getKoin().createScope() } // 页面销毁时关闭Scope,触发ViewModel销毁 DisposableEffect(screenScope) { onDispose { screenScope.close() } } // 从临时Scope获取ViewModel,确保每次都是新实例 val viewModel = koinViewModel<AddOrEditViewModel>(scope = screenScope) // 页面UI逻辑... }
替代方案:使用Factory声明(无生命周期管理)
如果不需要ViewModel的跨配置变更保留,可将ViewModel声明为factory,每次调用get()获取新实例:
// Koin模块声明 val appModule = module { factory { AddOrEditViewModel(get()) } } // Compose页面中获取 val viewModel = remember { getKoin().get<AddOrEditViewModel>() }
注意:此方式下ViewModel不会自动跟随页面生命周期销毁,需手动管理实例。
关键说明
- 使用临时Scope的方式既保留了ViewModel的生命周期管理,又能确保每次进入页面生成新实例。
- 避免直接使用时间戳作为
key,因为Scope未更新时,Koin仍会在同一Scope中复用实例。
内容的提问来源于stack exchange,提问作者hushed_voice
相关产品推荐
相关产品推荐

