如何通过Compose与Hilt在ViewModel间共享实例且随指定VM销毁
实现方案:基于Hilt自定义作用域+Subcomponent
核心思路是创建一个与ViewModel1生命周期绑定的自定义作用域,将Class1实例限定在此作用域内,ViewModel2通过依赖该作用域的实例实现共享,ViewModel1销毁时作用域内的实例随之销毁。
1. 定义自定义作用域注解
用于标记与ViewModel1生命周期绑定的实例范围:
@Scope @Retention(AnnotationRetention.RUNTIME) annotation class ViewModel1Scope
2. 创建自定义Subcomponent
这个Subcomponent作为自定义作用域的载体,负责提供Class1实例:
@ViewModel1Scope @Subcomponent interface ViewModel1Subcomponent { // 暴露Class1实例供外部依赖 fun getClass1(): Class1 // Subcomponent工厂,用于创建实例 @Subcomponent.Factory interface Factory { fun create(): ViewModel1Subcomponent } }
3. 在AppComponent中声明Subcomponent
让Hilt能够创建该Subcomponent的工厂实例:
@Singleton @Component(modules = [/* 你的其他模块 */]) interface AppComponent { // 提供Subcomponent的工厂 fun viewModel1SubcomponentFactory(): ViewModel1Subcomponent.Factory }
4. 绑定Class1到自定义作用域
创建Module将Class1实例与ViewModel1Scope绑定:
@Module @InstallIn(ViewModel1Subcomponent::class) object Class1Module { @Provides @ViewModel1Scope fun provideClass1(): Class1 { return Class1() } }
5. ViewModel1持有Subcomponent实例
ViewModel1通过注入Subcomponent工厂创建实例,并持有Class1:
class ViewModel1 @ViewModelInject constructor( private val subcomponentFactory: ViewModel1Subcomponent.Factory ) : ViewModel() { // 创建并持有Subcomponent实例,其生命周期与ViewModel1绑定 private val subcomponent = subcomponentFactory.create() // 暴露共享的Class1实例 val sharedClass1 = subcomponent.getClass1() override fun onCleared() { super.onCleared() // ViewModel1销毁时,subcomponent被回收,Class1实例也会随之销毁 } }
6. ViewModel2共享Class1实例
ViewModel2通过ViewModelProvider获取ViewModel1实例,进而拿到共享的Class1:
class ViewModel2 @ViewModelInject constructor( private val viewModelProvider: ViewModelProvider ) : ViewModel() { // 通过ViewModelProvider获取ViewModel1实例,确保同一作用域下拿到的是同一个实例 val sharedClass1: Class1 by lazy { viewModelProvider.get(ViewModel1::class.java).sharedClass1 } }
关键说明
- 自定义作用域
ViewModel1Scope确保Class1实例仅在ViewModel1的生命周期内存在,ViewModel1销毁时,持有的Subcomponent被回收,Class1实例也会被GC清理。 - 完全规避了
@SingletonComponent或@ActivityRetainedComponent的使用,仅基于ViewModel生命周期实现共享与销毁逻辑。 - 借助ViewModelProvider的特性,在同一个ViewModelStoreOwner(如Activity/Fragment)下,ViewModel1始终是单例实例,保证ViewModel2能拿到同一个Class1对象。
内容的提问来源于stack exchange,提问作者user1750283
相关产品推荐
相关产品推荐

