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

Dagger-Android场景下Fragment销毁时关联ViewModel未被销毁问题求解

问题根因

1. FragmentStateAdapter使用不符合规范

你当前的TradingTabAdapter在构造时就传入了提前实例化的两个子Fragment实例,且createFragment方法固定返回这两个实例。
按照FragmentStateAdapter的设计逻辑,不可见Fragment被销毁时仅会销毁Fragment的视图、触发生命周期回调,而你预创建的Fragment实例仍被Adapter持有,不会被GC回收。其内部通过by viewModels懒加载缓存的ViewModel属性也会一直保留在旧Fragment实例中,因此重建时不会重新触发ViewModelFactory的create方法,一直复用旧的僵尸ViewModel。

2. ViewModel作用域配置缺陷

你当前的ViewModelFactory被声明为@Singleton全局单例,且ViewModelModule中绑定ViewModel时未指定作用域,这也会增加ViewModel实例被全局复用的风险。


修复方案

步骤1:重构FragmentStateAdapter实现

不要预创建子Fragment实例,每次调用createFragment时都生成新的Fragment实例,配合Dagger的Provider实现实例动态生成:

// TradingTabAdapter 修改后代码
class TradingTabAdapter @Inject constructor(
  fragmentManager: FragmentManager,
  lifecycle: Lifecycle,
  // 注入子Fragment的Provider,每次get()返回新实例
  private val tradingStateTabFragmentProvider: Provider<TradingStateTabFragment>,
  private val allStockListTabFragmentProvider: Provider<AllStockListTabFragment>
) : FragmentStateAdapter(fragmentManager, lifecycle) {

  override fun createFragment(position: Int): Fragment =
    when (position) {
      0 -> tradingStateTabFragmentProvider.get()
      else -> allStockListTabFragmentProvider.get()
    }

  override fun getItemCount(): Int = 2
}

同步修改TradingTabModule中Adapter的提供逻辑:

@Module
class TradingTabModule {
  @Provides
  fun provideTradingTabAdapter(
    fragment: TradingTabFragment,
    tradingStateTabFragmentProvider: Provider<TradingStateTabFragment>,
    allStockListTabFragmentProvider: Provider<AllStockListTabFragment>
  ) = TradingTabAdapter(
    fragment.childFragmentManager,
    fragment.lifecycle,
    tradingStateTabFragmentProvider,
    allStockListTabFragmentProvider
  )
}

步骤2:调整ViewModel作用域(可选建议)

如果需要严格保证ViewModel和Fragment生命周期绑定,可以将ViewModel的绑定和ViewModelFactory的作用域调整为@FragmentScope,避免全局单例持有ViewModel实例:

// ViewModelModule 中增加作用域声明
@Binds
@IntoMap
@FragmentScope
@ViewModelKey(AllStockListTabViewModel::class)
abstract fun bindAllStockListTabViewModel(allStockListTabViewModel: AllStockListTabViewModel): ViewModel

效果验证

修改完成后,当Fragment C被系统销毁重建时,createFragment会返回全新的Fragment实例,新实例的viewModel属性未被懒加载,会重新调用ViewModelFactory生成新的ViewModel实例,和新Fragment的生命周期绑定,旧Fragment实例和对应的ViewModel会被GC回收,不会再出现ViewModel复用、viewModelScope无法工作的问题。


内容的提问来源于stack exchange,提问作者Austin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 12:27:06