[英]Dependency injection with Hilt of interface classes with suspend function blocks
我聲明了一個使用掛起 function 的 class。這個 class 應該是 Android 上的 Hilt 庫注入的 singleton 依賴項:
interface Foo {
suspend fun send(v: Int)
suspend fun receive(): Int
}
class FooImpl @Inject () {
var channel: Channel<Int>(2, BufferOverflow.DROP_OLDEST)
override suspend fun send(v: Int) {
channel.send(v)
}
override suspend fun receive(): Int {
channel.receive()
}
}
//FIRST CASE:
@Module
@InstallIn(SingletonComponent::class)
abstract class FooModule {
@Binds
abstract fun bindFoo(foo: FooImpl): Foo
}
然后,如果當我調用接收 function 時,它會永遠被阻止。 沒有收到數據,例如:
@AndroidEntryPoint
class Bar: Service {
@Inject
lateinit var foo: Foo
private val scope = CoroutineScope(Job() + Dispatchers.Default)
//...
fun doSomething() {
scope.launch() {
foo.receive()
//coroutine execution never reach this line
}
}
}
在這個簡單的例子中,由於Foo
是一個 singleton,我可以實施一個簡單的解決方法。 如果 Foo 在 Hilt 中以這種方式實現,我沒有問題:
//SECOND_CASE:
val FOO: Foo = FooImpl()
@Module
@InstallIn(SingletonComponent::class)
object FooModule {
@Provides
fun providesFoo(): Foo {
return FOO
}
}
我想知道這是 Hilt 錯誤還是我的 FIRST_CASE hilt 模塊實現有誤?
您永遠不會將FooImpl
聲明為 singleton,因此每次注入時,您都會獲得一個新實例。
如果您假設這是@InstallIn(SingletonComponent::class)
所做的,那么事實並非如此。 這個注解只告訴FooModule
本身應該是一個 singleton 並且不局限於 Activity、ViewModel 或 Fragment 的生命周期。
您需要將@Singleton
添加到FooImpl
或綁定它的方法:
選項1
interface Foo {
suspend fun send(v: Int)
suspend fun receive(): Int
}
@Singleton
class FooImpl @Inject constructor() : Foo {
...
}
@Module
@InstallIn(SingletonComponent::class)
abstract class FooModule {
@Binds
abstract fun bindFoo(foo: FooImpl): Foo
}
選項 2
interface Foo {
suspend fun send(v: Int)
suspend fun receive(): Int
}
class FooImpl @Inject constructor() : Foo {
...
}
@Module
@InstallIn(SingletonComponent::class)
abstract class FooModule {
@Singleton
@Binds
abstract fun bindFoo(foo: FooImpl): Foo
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.