Mik*_*koP 8 android dependency-injection android-service dagger-hilt
我有一个带有 Hilt 依赖注入的 Android 项目。我已经定义MyApplication并MyModule如下。
@HiltAndroidApp
class MyApplication : Application()
@Module
@InstallIn(ApplicationComponent::class)
abstract class MyModule {
@Binds
@Singleton
abstract fun bindMyRepository(
myRepositoryImpl: MyRepositoryImpl
): MyRepository
}
Run Code Online (Sandbox Code Playgroud)
MyRepositoryImpl实现MyRepository接口:
interface MyRepository {
fun doSomething(): String
}
class MyRepositoryImpl
@Inject
constructor(
) : MyRepository {
override fun doSomething() = ""
}
Run Code Online (Sandbox Code Playgroud)
我现在可以将此实现注入MyRepository到 ViewModel 中:
class MyActivityViewModel
@ViewModelInject
constructor(
private val myRepository: MyRepository,
) : ViewModel() { }
Run Code Online (Sandbox Code Playgroud)
这按预期工作。但是,如果我尝试将存储库注入服务,则会收到错误消息java.lang.Class<MyService> has no zero argument constructor:
class MyService
@Inject
constructor(
private val myRepository: MyRepository,
): Service() { }
Run Code Online (Sandbox Code Playgroud)
活动也会发生同样的错误:
class MyActivity
@Inject
constructor(
private val myRepository: MyRepository,
) : AppCompatActivity(R.layout.my_layout) { }
Run Code Online (Sandbox Code Playgroud)
我在注射时做错了什么?
Ahm*_*ndy 13
从我们如何将依赖项注入 Android 类的文档中,我们可以了解到以下内容:
Hilt 可以为具有 @AndroidEntryPoint 注释的其他 Android 类提供依赖项。
Hilt 目前支持以下 Android 类:
Application(通过使用@HiltAndroidApp)ActivityFragmentViewServiceBroadcastReceiver
因此,当您对这些 Android 类中的任何一个进行子类化时,您不会要求 Hilt 通过构造函数注入依赖项。相反,您使用 注释它@AndroidEntryPoint,并通过使用 注释属性来要求 Hilt 注入其依赖项@Inject:
@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() {
@Inject
lateinit var mAdapter: SomeAdapter
...
}
Run Code Online (Sandbox Code Playgroud)
所以,你的情况,你应该注入MyRepository在MyActivity和MyService这样的:
@AndroidEntryPoint
class MyService: Service() {
@Inject
lateinit var myRepository: MyRepository
...
}
@AndroidEntryPoint
class MyActivity: AppCompatActivity(R.layout.my_layout) {
@Inject
lateinit var myRepository: MyRepository
...
}
Run Code Online (Sandbox Code Playgroud)
并记住:
Hilt 注入的字段不能是私有的
这就是 Hilt 支持的 Android 类。
如果您想知道 Hilt 不支持的类(例如:)怎么办ContentProvider?!我建议从codelab 上的本教程@EntryPoint 注释中学习如何使用(也不要忘记查看文档以了解如何在 Hilt 不支持的类中注入依赖项)。
@Inject您在类上的使用MyService就好像MyService要在其他位置注入一样。
如果我理解正确的话,你想要的东西更类似于:
@AndroidEntryPoint
class MyService : Service() {
@Inject
lateinit var myRepository: MyRepository
}
Run Code Online (Sandbox Code Playgroud)
小智 5
此外,如果您在您的服务中覆盖 onCreate - 不要忘记添加 super.onCreate() 否则您将获得无法初始化 myRepository 值的运行时异常(我在重构我的服务期间一直在努力解决这个错误,所以也许它会对某人有帮助)
@AndroidEntryPoint
class MyService : Service() {
@Inject
lateinit var myRepository: MyRepository
override fun onCreate() {
super.onCreate()
}
}
Run Code Online (Sandbox Code Playgroud)