使用 Hilt 将存储库注入到 Android 中的服务中

问题描述 投票:0回答:4

我有一个带有 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 dependency-injection android-service dagger-hilt
4个回答
79
投票

从有关如何将依赖项注入 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 支持的类中注入依赖项)。


31
投票
另外,如果您在服务中重写 onCreate - 不要忘记添加 super.onCreate() ,否则您将收到运行时异常,即 myRepository 值无法初始化(在重构我的服务期间,我在这个错误上挣扎了一段时间,所以也许这对某人会有帮助)

@AndroidEntryPoint class MyService : Service() { @Inject lateinit var myRepository: MyRepository override fun onCreate() { super.onCreate() } }
    

6
投票
您在

@Inject

 类上使用 
MyService
 就像将 
MyService
 注入到其他位置一样。

如果我理解正确,你想要的东西更类似于:

@AndroidEntryPoint class MyService : Service() { @Inject lateinit var myRepository: MyRepository }
    

0
投票
对我来说,问题是在另一个字段的初始值设定项中使用注入字段。

@Inject lateinit var dispatcherProvider: DispatcherProvider private val serviceJob = SupervisorJob() private val serviceScope = CoroutineScope(dispatcherProvider.main + serviceJob)
dispatcherProvider 尚未设置,无法在 CoroutineScope 的构造函数中使用

© www.soinside.com 2019 - 2024. All rights reserved.