繁体   English   中英

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

[英]Injecting a repository into a Service in Android using 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) { }

我在注射时做错了什么?

从我们如何将依赖项注入 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 

    ...

}

因此,在您的情况下,您应该像这样在MyActivityMyService中注入MyRepository

@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 不支持的类中注入依赖项)。

此外,如果您在服务中覆盖 onCreate - 不要忘记添加 super.onCreate() 否则您将获得无法初始化 myRepository 值的运行时异常(我在重构我的服务期间一直在努力解决此错误,所以也许它会对某人有所帮助)

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

    override fun onCreate() {
        super.onCreate()

    }
}

您在MyService类上使用@Inject就好像要在其他位置注入MyService

如果我理解正确,您想要更类似于:

@AndroidEntryPoint
class MyService : Service() {

    @Inject
    lateinit var myRepository: MyRepository

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM