Dagger Hilt 错误注入 ActivityContext

Dagger Hilt error injecting ActivityContext

我在 ViewModel 中注入 Dagger-Hilt 一个 class,它依赖于 @ActivityContext,这个模块安装在 ActivityComponent 中,作用域为 activity 每当我尝试编译时它都会抛出一个错误。为了您的信息,我有其他模块 ActivityRetainedComponent 和 SingletonComponent 注入 @ApplicationContext.

现在我想弄清楚这个错误是什么意思。

error: [Dagger/MissingBinding] com.rober.fileshortcut_whereismyfile.utils.PermissionsUtils cannot be provided without an @Inject constructor or an @Provides-annotated method.
  public abstract static class SingletonC implements App_GeneratedInjector,
                         ^
      com.rober.fileshortcut_whereismyfile.utils.PermissionsUtils is injected at
          com.rober.fileshortcut_whereismyfile.ui.fragments.filefragment.FileViewModel(�, permissionsUtils, �)
      com.rober.fileshortcut_whereismyfile.ui.fragments.filefragment.FileViewModel is injected at
          com.rober.fileshortcut_whereismyfile.ui.fragments.filefragment.FileViewModel_HiltModules.BindsModule.binds(vm)
      @dagger.hilt.android.internal.lifecycle.HiltViewModelMap java.util.Map<java.lang.String,javax.inject.Provider<androidx.lifecycle.ViewModel>> is requested at
          dagger.hilt.android.internal.lifecycle.HiltViewModelFactory.ViewModelFactoriesEntryPoint.getHiltViewModelMap() [com.rober.fileshortcut_whereismyfile.App_HiltComponents.SingletonC ? com.rober.fileshortcut_whereismyfile.App_HiltComponents.ActivityRetainedC ? com.rober.fileshortcut_whereismyfile.App_HiltComponents.ViewModelC]

这是代码(我不认为这里有什么问题)

@Module
@InstallIn(ActivityComponent::class)
object PermissionModule {

    @ExperimentalCoroutinesApi
    @Provides
    @ActivityScoped
    fun providePermissionsHelper(
        @ActivityContext context: Context,
    ) = PermissionsUtils(context)
}
@HiltViewModel
@ExperimentalCoroutinesApi
class FileViewModel @Inject constructor(
    private val class1: Class1,
    private val class2: Class2,
    private val class3: Class3,
    private val permissionsUtils: PermissionsUtils //Here's the one I'm injecting
)

我的猜测:它告诉我不能在 ActivityComponent 中注入,因为在 ActivityRetainedComponent/SingletonComponent/ViewModelComponent 中注入了 FileViewModel,因为在该组件中安装了提供给 viewmodel 的其他依赖项?

问题:这里到底发生了什么?我缺少什么,是否有使用 ActivityComponent 的解决方案? class!

我真的需要 @ActivityContext

编辑: 当我更改为 @InstallIn(ActivityRetainedComponent::class) 并将上下文更改为 @ApplicationContext context: Context 时,这有效,请注意它适用于 SingletonComponent/ViewModelComponent/ActivityRetainedComponent,它说得通。但我仍然不知道如何让它工作 @ActivityComponent

编辑 2: 我得出的结论是不可能的,因为您在 ViewModel 中安装并且与 ViewModel 一起使用的 组件是 Singleton/ActivityRetained/ViewModel,因此无法在 ViewModel 中注入 ActivityContext,因为它需要组件 @ActivityComponent,并且它比 ViewModelComponent 低 1 级。

来源: https://dagger.dev/hilt/components#fn:1

so there's no way to inject ActivityContext in a ViewModel since it requires the component @ActivityComponent and this is 1 level below of ViewModelComponent.

你明白了。

从生命周期的角度考虑 Dagger/Hilt 组件(和范围)。在 Android 中,ViewModel 的生命周期比其包含的 ActivityFragment 更长。这就是 class 的全部要点,只是不幸的名字。将它们视为 RetainedInstanceAnObjectThatSurvivesActivityConfigurationChanges 可能会有所帮助。是的,这些不像 ViewModel.

那样吸引人

如果你将一个短期对象(Activity)注入到一个长期对象(ViewModel)中,后者将保留对前者的引用。这是内存泄漏 - Activity 及其包含的所有内容(例如视图、位图)即使不再使用,也会保留在内存中。其中几个,你就有 OutOfMemoryError.

的风险

然而,反过来——即将一个长寿命对象注入一个短寿命对象——是安全的。这就是为什么你让它与 Singleton/ActivityRetained/ViewModel 组件一起工作。

Hilt 的组件层次结构使您更难造成内存泄漏。所有这些都发生在编译时,与基于运行时的解决方案相比,它可以为您提供更快的反馈。比你的用户通过崩溃发现的要好得多!