Hilt中SingletonComponent与ActivityComponent作用域相关问题咨询
背景场景
我开发的应用包含三个Activity,启动流程为Activity A → Activity B → Activity C,跳转至下一个Activity时会销毁前一个Activity。注入对象的代码如下:
@Module @InstallIn(SingletonComponent::class) class MyProvider { // Provides object in Activity A @Provides fun provideTheObjectA(): SomeObjectA { return SomeObjectA() } } @Module @InstallIn(ActivityComponent::class) class AvtivtyBProvider { // Provides object in Activity B @Provides fun provideTheObjectB(): SomeObjectB { return SomeObjectB() } } class ActivtyA: AppCompatActivity(){ @Inject lateinit var someObjectA: SomeObjectA } class ActivtyB: AppCompatActivity(){ @Inject lateinit var someObjectB: SomeObjectB }
问题与解答
1. 当Activity A销毁时,SomeObjectA会被销毁/垃圾回收吗?(它在SingletonComponent作用域下提供,未使用@Singleton注解)
没错,你的判断是对的。虽然MyProvider被安装在SingletonComponent中,但provideTheObjectA没有标注@Singleton作用域,所以每次注入时Dagger都会生成一个新的SomeObjectA实例。当Activity A销毁后,它持有的someObjectA引用会被释放,这个实例失去所有引用后,最终会被垃圾回收。
2. 若我为SomeObjectA添加@Singleton注解,是否即使Activity A销毁,该对象也不会被销毁/垃圾回收?未使用@Singleton注解时,@SingletonComponent的意义是什么?
- 是的。添加
@Singleton注解后,Dagger会在SingletonComponent中维护这个实例的唯一引用,只要应用进程还在运行,这个实例就不会被回收——哪怕所有依赖它的组件(比如Activity A)都销毁了。 - 未加
@Singleton时,@InstallIn(SingletonComponent::class)的核心意义是:把这个@Provides方法的提供能力放到全局可访问的组件层级,所有依赖SingletonComponent的子组件(比如ActivityComponent、FragmentComponent等)都能获取这个对象,但每次注入依然会生成新实例。
3. 我认为当Activity B销毁时,SomeObjectB会被销毁/垃圾回收,是否正确?
正确。AvtivtyBProvider安装在ActivityComponent中,虽然provideTheObjectB没加@ActivityScoped,但ActivityComponent的生命周期和Activity完全绑定。当Activity B销毁时,ActivityComponent会被销毁,它关联的所有对象(包括每次注入生成的SomeObjectB实例)都会失去组件的引用,再加上Activity B本身的引用也消失,最终会被垃圾回收。
4. 我在创建SomeObjectB实例时未使用@ActivityScoped注解,这会有什么区别?
如果添加@ActivityScoped,在同一个Activity B的生命周期内,所有注入SomeObjectB的地方都会拿到同一个实例;如果不加,每次注入都会生成全新的实例。
举个实际例子:如果Activity B里有两个Fragment都注入了SomeObjectB,不加@ActivityScoped的话,两个Fragment拿到的是完全独立的实例;加了之后,两个Fragment会共享同一个实例,这个实例的生命周期和Activity B保持一致。
5. 仅使用@Provides注解而不指定任何作用域,最终意味着什么?
这表示这个提供的对象是**无作用域(unscoped)**的,每次调用该@Provides方法(也就是每次注入操作)都会创建一个全新的实例。
另外,无作用域的@Provides方法可以被安装在任何作用域的组件中,但它的实例生命周期完全由依赖它的对象决定——如果依赖它的对象销毁且没有其他引用,这个实例就会被回收。
内容的提问来源于stack exchange,提问作者abhishek maharajpet

