基于Hilt自定义作用域的Feature组件实例销毁方案问询
问题解答
关于CustomComponentManager的持有情况
是的,因为你给CustomComponentManager标注了@Singleton,它的生命周期和应用级的SingletonComponent绑定,只要应用进程还在运行,Dagger就会一直持有这个实例,不会在A->B->Home流程结束后自动销毁。
实现流程结束后销毁Feature作用域的方案
你的核心需求是让Feature A的作用域随流程销毁,而当前用单例ComponentManager的方式违背了这个需求——单例是全局复用的,无法做到流程级的清理。下面是具体的修正方案:
1. 移除ComponentManager的单例特性,改用流程绑定的生命周期管理
Feature级的作用域应该和流程的生命周期绑定,而不是全局单例。推荐用ViewModel作为流程的生命周期容器,因为ViewModel的onCleared()会在最后一个关联页面退出时触发,刚好对应流程结束的时机:
第一步:创建Feature专属的Scope ViewModel
这个ViewModel专门负责管理MyCustomComponent的生命周期:
@HiltViewModel class FeatureAScopeViewModel @Inject constructor( private val componentBuilder: MyCustomComponentBuilder ) : ViewModel(), GeneratedComponentManager<MyCustomComponent> { private var component: MyCustomComponent? = null // 初始化Feature组件,传入必要参数 fun initFeatureComponent(employee: Employee) { component = componentBuilder.provideEmployee(employee).build() } // 手动清理组件,也可以在onCleared自动执行 private fun clearFeatureComponent() { component = null // 解除引用,让旧组件被GC回收 } override fun generatedComponent(): MyCustomComponent { return component ?: throw IllegalStateException("Feature A组件未初始化") } // 流程结束时自动清理 override fun onCleared() { clearFeatureComponent() super.onCleared() } }
第二步:修改A/B ViewModel,复用同一个Scope ViewModel
在A、B的ViewModel中,通过ViewModelProvider获取同一个FeatureAScopeViewModel(只要在同一个导航栈/父生命周期下,ViewModel会自动复用):
AViewModel修改后:
@HiltViewModel class AViewModel @Inject constructor( private val person: Person, private val viewModelFactory: ViewModelProvider.Factory ) : ViewModel() { // 获取Feature专属的Scope ViewModel private val featureScopeVm = viewModelFactory.create(FeatureAScopeViewModel::class.java) init { // 初始化Feature组件 featureScopeVm.initFeatureComponent(Employee()) val employee = EntryPoints.get(featureScopeVm, MyCustomEntryPoint::class.java).getEmployee() Log.d( "Test", "CVM Person: $person Hashcode: ${person.hashCode()} && Employee: $employee " + "Hashcode: ${employee.hashCode()}" ) } }
BViewModel修改后:
@HiltViewModel class BViewModel @Inject constructor( private val person: Person, private val viewModelFactory: ViewModelProvider.Factory ) : ViewModel() { private val featureScopeVm = viewModelFactory.create(FeatureAScopeViewModel::class.java) private val employee = EntryPoints.get(featureScopeVm, MyCustomEntryPoint::class.java).getEmployee() init { Log.d( "Test", "DVM Person: $person Hashcode: ${person.hashCode()} && Employee: $employee " + "Hashcode: ${employee.hashCode()}" ) } }
2. 清理原CustomComponentManager
直接删除原有的CustomComponentManager类,或者移除它的@Singleton注解并废弃,避免混淆。
3. 补充说明
- 这种方式下,
MyCustomComponent的生命周期完全绑定到FeatureAScopeViewModel:当从B页面返回Home页面时,关联的ViewModel会被销毁,onCleared()触发,组件被置为null,相关实例会被GC回收,彻底销毁Feature A的作用域。 - 如果用Compose导航,也可以选择将组件绑定到
NavBackStackEntry的生命周期上,原理类似——监听导航栈条目的销毁事件来清理组件。
内容的提问来源于stack exchange,提问作者Shaon
相关产品推荐
相关产品推荐

