当前位置: 首页 > 知识库问答 >
问题:

Android Kotlin Hilt:无法在非活动类中@Inject

贡俊
2023-03-14

我最近开始学习Hilt,现在它给我的头疼比快乐多,但是我喜欢挑战,所以让我们开门见山吧。

我在理解如何在非活动类中注入方面有很多问题,例如注入一个上下文或任何其他类。

到目前为止,我的大多数非活动类都是对象(单例),但由于我无法注入对象,我决定将它们转换为类。

我尝试用字段注入来注入,因为如果我用@ AndroidEntryPoint来使用构造函数注入,它会报错类必须从AppCompatActivity继承...

让我们举一个简单的例子来说明我的问题。

我的应用程序是一个多模块应用程序,我在“通用”模块中有一个 AWFile 类(可从所有其他模块访问 [我现在说的是 Gradle 模块,而不是 Hilt 模块]),它承载文件操作,所以为了开始使用 Hilt 测试注入,我创建了一个方法 doSomething,并且在 doSomething 中我试图访问 appSettings, 一个类,我保存通过字段注入的所有应用程序配置,但即使应用程序构建良好,我也总是在字段中得到 null - 实际上是错误(我也不确定如何获取上下文)。

A应用:

@HiltAndroidApp
class AWApplication  : MultiDexApplication() {

}

AWFile:

class AWFile @Inject constructor() {

    @Inject
    lateinit var app: AppSettings

    @Inject
    lateinit var context: Context

        fun doSomething(){
            var color = app.actionBarEndColor
            var ctx = context
        }
        ...
}

依赖项(在应用程序模块中):

@Module
@InstallIn(SingletonComponent::class)
class Dependencies {

    @Provides
    @ApplicationContext
    fun provideContext(@ApplicationContext appContext: Context): Context {
        return appContext
    }
}

“通用”项目模块中的依赖关系:

@Module
@InstallIn(SingletonComponent::class)
class Dependencies {
    @ApplicationContext
    lateinit var appContext: Context

    @Provides
    @Singleton
    fun bindsAppSettings(): AppSettings {
        return AppSettings()
    }

    @Provides
    @Singleton
    fun bindsAWFile(): AWFile {
        return AWFile()
    }
}

主要活动:

@AndroidEntryPoint
class MainActivity : FragmentActivity() {
    @Inject
    lateinit var awFile: AWFile

    @Inject
    lateinit var app: AppSettings

    override fun onCreate(savedInstanceState: Bundle?) {
        requestWindowFeature(Window.FEATURE_CUSTOM_TITLE)
        super.onCreate(savedInstanceState)

        awFile.doSomething()
    }

调试到AWFile时的错误

kotlin.UninitializedPropertyAccessException: lateinit property app has not been initialized (the same for context)

编辑1:按照@CommonsWare的建议,尝试在AWFile中进行构造函数注入(而不是字段注入)。

AWFile声明:

class AWFile @Inject constructor(private var app: AppSettings, private var context: Context)

“通用”模块

@Module
@InstallIn(SingletonComponent::class)
class Dependencies {
    @ApplicationContext
    lateinit var appContext: Context

    @Provides
    @Singleton
    fun bindsAppSettings(): AppSettings {
        return AppSettings()
    }

    @Provides
    @Singleton
    fun bindsAWFile(): AWFile {
        return AWFile()
    }
}

结果:

应用程序不会生成。它报错没有为bindsAWFile()中的应用程序传递参数

编辑2:仍然遵循@CommonsWare的建议。

依赖性:

@Module
@InstallIn(SingletonComponent::class)
class Dependencies {
    @ApplicationContext
    lateinit var appContext: Context

    @Provides
    @Singleton
    fun bindsAppSettings(): AppSettings {
        return AppSettings()
    }

    @Provides
    @Singleton
    fun bindsAWFile(appSettings: AppSettings): AWFile {
        return AWFile(appSettings, appContext)
    }
}

结果:

...Caused by: kotlin.UninitializedPropertyAccessException: lateinit property appContext has not been initialized
        at dependencies.Dependencies.getAppContext(Dependencies.kt:18)...

编辑 3:已解决。

应用依赖类:

@Module
@InstallIn(SingletonComponent::class)
class Dependencies {

    @Provides
    @Singleton
    fun provideContext(@ApplicationContext appContext: Context): Context {
        return appContext
    }
}

“共享资源”模块依赖类:

@Module
@InstallIn(SingletonComponent::class)
class Dependencies {

    @Provides
    @Singleton
    fun bindsAppSettings(): AppSettings {
        return AppSettings()
    }

    @Provides
    @Singleton
    fun bindsAWFile(appSettings: AppSettings, context: Context): AWFile {
        return AWFile(appSettings, context)
    }
}

现在它开始工作了,关键是首先提供应用程序中的上下文依赖性模块,然后将appSettings和上下文作为参数包含到bindsAWFile方法声明中,然后按照@CommonsWare的建议传递给AWFile。

希尔特是一场噩梦,但感谢您的时间@CommonsWare。

共有1个答案

严恩
2023-03-14

好吧,在挣扎了几个小时后,我找到了一个解决方案。

应用依赖类:

@Module
@InstallIn(SingletonComponent::class)
class Dependencies {

    @Provides
    @Singleton
    fun provideContext(@ApplicationContext appContext: Context): Context {
        return appContext
    }
}

“共享资源”模块依赖类:

@Module
@InstallIn(SingletonComponent::class)
class Dependencies {

    @Provides
    @Singleton
    fun bindsAppSettings(): AppSettings {
        return AppSettings()
    }

    @Provides
    @Singleton
    fun bindsAWFile(appSettings: AppSettings, context: Context): AWFile {
        return AWFile(appSettings, context)
    }
}

其余代码保持不变。

现在它开始工作了,关键是首先提供应用程序中的上下文依赖性模块,然后将AppSettings和上下文作为参数包含到bindsAWFile方法声明中,然后按照@CommonsWare的建议传递给AWFile。

请注意@ApplicationContext的重要性。

 类似资料:
  • 错误是: 错误:(50,17)错误:没有为startActivities(Intent)方法Activity找到合适的方法。startActivities(Intent[],Bundle)不适用(实际和正式的参数列表长度不同)方法Activity.startActivities(Intent[])方法上下文twrapper.startactivities(Intent[],Bundle)不适用(实

  • 在我的非活动类中,我请求了一个Fine location权限,但回调onRequestPermissionsResult“永远不会被调用”。现在我看到了一些与此相关的问题,但他们都认为请求是从活动或片段发出的,没有人考虑从非活动类发出请求。这是我的代码 这是onRequestPermissionResultCallback方法的实现 解决了:正如一些人提到的“activity”的onRequest

  • 我已经创建了一个片段,当点击一个按钮时,会弹出一个类似对话框的ALTERVIEW。在该视图中包括谷歌登录按钮。当我连接到firebase并在startActivityForResult之后继续执行时,我需要重写onActivityResult方法。但弹出对应的类扩展了另一个对话框类,不能重写onActivityResult方法。当要重写时,它显示方法并没有从其超类错误重写方法。如何解决这个问题。以

  • 问题内容: 在添加异步任务之前,我已经对代码进行了一些更改,我的应用程序可以正常运行其远程服务器上的身份验证用户名和密码,但是在登录成功消息消失后​​无法启动其他活动。有人建议我现在添加一个异步任务,但是我输入正确的用户名和密码后它将停止工作。当我输入错误的用户名和密码时,其工作正常将显示错误的用户名密码消息。如果有人能够知道会出现什么错误,请帮助我。 码- 日志猫 QuestionnActivi

  • 我已经搜索了这个错误,并找到了许多解决方案,但我无法解决这个问题,因为我是Android的初学者 舱单在下面 安装应用程序后,它第一次工作,但当我们关闭并重新打开时,它崩溃了,不幸的是,应用程序已经关闭,你有任何想法,它将非常感谢:) 谢了!