使用Hilt

问题描述

我有一个带有Hilt依赖项注入的Android项目。我对MyApplicationMyModule的定义如下。

@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 

    ...

}

因此,在您的情况下,应像这样在MyRepositoryMyActivity中注入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

}