繁体   English   中英

Android + Kotlin + Hilt:不能@Inject in a non activity class

[英]Android + Kotlin + Hilt: Cannot @Inject in a non activity class

我最近开始学习 Hilt,现在它让我头疼多于快乐,但我喜欢挑战,所以让我们 go 进入正题。

我在理解如何注入非活动类时遇到很多问题,例如注入上下文或任何其他 class。

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

我正在尝试使用字段注入进行注入,因为如果我将构造函数注入与@AndroidEntryPoint一起使用,它会抱怨 class 必须继承自 AppCompatActivity 左右...

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

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

AW应用:

@HiltAndroidApp
class AWApplication  : MultiDexApplication() {

}

文件:

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 > doSomething 时的错误:

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

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

AW文件声明:

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() > AWFile(我用来提供 AWFile 的方法)中没有为应用程序传递参数,我不知道如何传递它:s

编辑 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:已解决。

应用程序依赖项 class:

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

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

“公共”模块依赖关系 class:

@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。

Hilt 是一场噩梦,但感谢您花时间@CommonsWare。

好的,经过几个小时的努力,我得到了解决方案。

应用程序依赖项 class:

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

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

“公共”模块依赖关系 class:

@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)
    }
}

代码rest保持不变。

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

注意@ApplicationContext的重要性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM