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

基于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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 01:02:13