Hilt creating different instances of view model inside same activity

rit*_*302 6 android dagger dagger-hilt

After recently migrating from Dagger to Hilt I started observing very strange behavior with respect to ViewModels. Below is the code snippet:


@HiltAndroidApp
class AndroidApplication : Application() {}

@Singleton
class HomeViewModel @ViewModelInject constructor() :
    ViewModel() {}

@AndroidEntryPoint
class HomeFragment : Fragment(R.layout.fragment_home) {

    private val homeViewModel by viewModels<HomeViewModel>()

    override fun onResume() {
        super.onResume()
        Timber.i("hashCode: ${homeViewModel.hashCode()}")
    }
}


@AndroidEntryPoint
class SomeOtherFragment : Fragment(R.layout.fragment_home) {

    private val homeViewModel by viewModels<HomeViewModel>()

    override fun onResume() {
        super.onResume()
        Timber.i("hashCode: ${homeViewModel.hashCode()}")
    }
}

Run Code Online (Sandbox Code Playgroud)

The value of hashCode isn't consistent in all the fragments. I am unable to figure out what else am I missing for it to generate singleton instance of viewmodel within the activity.

I am using single activity design and have added all the required dependencies.

ian*_*ake 17

当您使用 时by viewModels,您正在创建一个作用域为该单个 Fragment 的 ViewModel - 这意味着每个 Fragment 将拥有该 ViewModel 类的自己的单独实例。如果您希望将单个 ViewModel 实例范围限定为整个 Activity,则您需要使用by activityViewModels

private val homeViewModel by activityViewModels<HomeViewModel>()
Run Code Online (Sandbox Code Playgroud)


Epi*_*rce 9

Ian说的是对的,by viewModels是Fragment的扩展功能,它会使用Fragment作为ViewModelStoreOwner。

如果您需要将其范围限定为 Activity,则可以使用by activityViewModels.

但是,您通常不需要 Activity 范围内的 ViewModel。它们在单活动应用程序中实际上是全局的。

要创建 Activity 全局的无状态组件,可以使用@ActivityRetainedScopeHilt 中的 。这些将可供您在 Activity 或 Fragment 中创建的 ViewModel 使用。

要创建有状态保留组件,您应该依赖 ~~@ViewModelInject@Assisted~~@HiltViewModel@Inject constructor获取 SavedStateHandle。

那时,您很可能真正想要的是 NavGraph 范围的 ViewModel,而不是 Activity 范围的 ViewModel。

要将 SavedStateHandle 放入 Fragment 内的 NavGraph 范围的 ViewModel 中,请使用val vm = androidx.hilt.navigation.fragment.hiltNavGraphViewModels(R.navigation.nav_graph_id).

如果您不使用 Hilt,则可以使用= navGraphViewModels,但可以使用默认的 ViewModelProvider.Factory 或 CreationExtras 获取 SavedStateHandle。