我有一个带有 Hilt 依赖注入的 Android 项目。我定义了
MyApplication
和 MyModule
如下。
@HiltAndroidApp
class MyApplication : Application()
@Module
@InstallIn(ApplicationComponent::class)
abstract class MyModule {
@Binds
@Singleton
abstract fun bindMyRepository(
myRepositoryImpl: MyRepositoryImpl
): MyRepository
}
MyRepositoryImpl
实现 MyRepository
接口:
interface MyRepository {
fun doSomething(): String
}
class MyRepositoryImpl
@Inject
constructor(
) : MyRepository {
override fun doSomething() = ""
}
我现在可以将
MyRepository
的实现注入到 ViewModel 中:
class MyActivityViewModel
@ViewModelInject
constructor(
private val myRepository: MyRepository,
) : ViewModel() { }
这按预期工作。但是,如果我尝试将存储库注入到服务中,则会收到错误
java.lang.Class<MyService> has no zero argument constructor
:
class MyService
@Inject
constructor(
private val myRepository: MyRepository,
): Service() { }
活动也会出现同样的错误:
class MyActivity
@Inject
constructor(
private val myRepository: MyRepository,
) : AppCompatActivity(R.layout.my_layout) { }
我注射时做错了什么?
从有关如何将依赖项注入 Android 类的文档中,我们可以了解以下内容:
Hilt 可以为具有 @AndroidEntryPoint 注解的其他 Android 类提供依赖关系。
Hilt 目前支持以下 Android 类:
(通过使用Application
)@HiltAndroidApp
(通过使用ViewModel
)@HiltViewModel
Activity
Fragment
View
Service
BroadcastReceiver
因此,当您对任何这些 Android 类进行子类化时,您不会要求 Hilt 通过构造函数注入依赖项。相反,您可以使用
@AndroidEntryPoint
对其进行注释,并要求 Hilt 通过使用 @Inject
注释该属性来注入其依赖项:
@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() {
@Inject
lateinit var mAdapter: SomeAdapter
...
}
因此,在您的情况下,您应该将
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
...
}
请记住:
由 Hilt 注入的字段不能是私有
这就是 Hilt 支持的 Android 类。
如果您想知道 Hilt 不支持的类(例如:
ContentProvider
)怎么办?!我建议从本教程Codelab 上的@EntryPoint 注释中学习如何操作(也不要忘记检查文档以了解如何在 Hilt 支持的类中注入依赖项)。
@AndroidEntryPoint
class MyService : Service() {
@Inject
lateinit var myRepository: MyRepository
override fun onCreate() {
super.onCreate()
}
}
@Inject
类上使用
MyService
就像将
MyService
注入到其他位置一样。如果我理解正确,你想要的东西更类似于:
@AndroidEntryPoint
class MyService : Service() {
@Inject
lateinit var myRepository: MyRepository
}
@Inject
lateinit var dispatcherProvider: DispatcherProvider
private val serviceJob = SupervisorJob()
private val serviceScope = CoroutineScope(dispatcherProvider.main + serviceJob)
dispatcherProvider 尚未设置,无法在 CoroutineScope 的构造函数中使用