Dagger2/Android:setRetainInstance(true)的@FragmentScoped子组件随旋转重建
Dagger2:保留的Fragment每次注入都获取新依赖实例的问题分析
首先可以明确地说:这是Dagger2的预期行为,但你可以通过调整组件的作用域和依赖关系来解决这个问题。
为什么会出现这种情况?
当屏幕旋转时,Activity实例会被系统销毁并重建,绑定在Activity上的子组件(比如你的ActivityComponent)也会跟着一起重建。虽然你的Fragment通过setRetainInstance(true)保留了实例,但默认情况下,Fragment的注入依赖是依附于它所在的Activity子组件的。每次Activity重建后,新的ActivityComponent会创建全新的Fragment子组件,这就导致即使Fragment本身没被销毁,注入的依赖还是会变成新实例。
如何解决这个问题?
要让保留的Fragment的依赖实例也跟着Fragment一起存活,你需要让Fragment拥有独立于Activity的组件作用域:
1. 自定义Fragment专属的作用域
首先创建一个自定义的作用域注解,用来标记和Fragment生命周期绑定的依赖:
@Scope @Retention(AnnotationRetention.RUNTIME) annotation class FragmentScope
2. 让Fragment子组件直接依赖AppComponent
不要让Fragment子组件依附于ActivityComponent,而是直接将它挂在Singleton级别的AppComponent下,这样Fragment组件的生命周期就只和Fragment实例绑定:
// 定义Fragment子组件,使用自定义的FragmentScope @FragmentScope @Subcomponent(modules = [YourFragmentModule::class]) interface YourFragmentComponent { fun inject(fragment: YourRetainedFragment) @Subcomponent.Factory interface Factory { fun create(): YourFragmentComponent } } // 在AppComponent中声明Fragment子组件的工厂 @Singleton @Component(modules = [/* 你的App级模块 */]) interface AppComponent { fun yourFragmentComponentFactory(): YourFragmentComponent.Factory }
3. 只在Fragment第一次依附时注入
因为Fragment被保留了,所以不需要每次重建都调用注入,只在第一次onAttach时执行一次即可:
class YourRetainedFragment : Fragment() { private var isInjected = false override fun onAttach(context: Context) { super.onAttach(context) if (!isInjected) { val appComponent = (context.applicationContext as YourApp).appComponent appComponent.yourFragmentComponentFactory().create().inject(this) isInjected = true } } // 其他Fragment代码... }
额外注意事项
- 确保你的Fragment依赖都用
@FragmentScope标注,这样Dagger会保证这些依赖实例和Fragment同生命周期,不会被重复创建。 - 不要在
onCreateView或其他每次重建都会触发的方法里调用注入,否则还是会重复创建依赖实例。
内容的提问来源于stack exchange,提问作者TonyR
相关产品推荐
相关产品推荐

