问题描述
我有一个带有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) { }
注射有什么问题?
解决方法
从有关如何Inject dependencies into Android classes的文档中,我们可以学习以下内容:
Hilt可以提供对具有@AndroidEntryPoint批注的其他Android类的依赖。
Hilt当前支持以下Android类:
Application
(通过使用@HiltAndroidApp
)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
)怎么办?我建议您从本教程@EntryPoint annotation on codelab中学习方法(也不要忘记查看文档来了解如何Inject dependencies in classes not supported by Hilt)。
此外,如果您在服务中覆盖 onCreate - 不要忘记添加 super.onCreate() 否则您将获得无法初始化 myRepository 值的运行时异常(在重构我的服务期间,我一直在为这个错误而苦苦挣扎)所以也许它会对某人有所帮助)
@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
}