简体   繁体   English

带有暂停 function 块的接口类 Hilt 的依赖注入

[英]Dependency injection with Hilt of interface classes with suspend function blocks

I declare a class that uses suspend function. This class is meant to be a singleton dependency injected by Hilt library on Android:我声明了一个使用挂起 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
 }

Then if when I call the receive function it get blocked forever.然后,如果当我调用接收 function 时,它会永远被阻止。 No data is received, example:没有收到数据,例如:

@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
    }
  }
}

In this simple case, as Foo is a singleton I could implement a simple work around.在这个简单的例子中,由于Foo是一个 singleton,我可以实施一个简单的解决方法。 If Foo is implemented this way within Hilt, I have no trouble:如果 Foo 在 Hilt 中以这种方式实现,我没有问题:

//SECOND_CASE:
val FOO: Foo = FooImpl()

@Module
@InstallIn(SingletonComponent::class)
object FooModule {
   @Provides
   fun providesFoo(): Foo {
      return FOO
   }
}

I am wondering weither it is a Hilt bug or my FIRST_CASE hilt module implementation is wrong?我想知道这是 Hilt 错误还是我的 FIRST_CASE hilt 模块实现有误?

You never declare FooImpl as a singleton, so every time it is injected, you get a fresh instance.您永远不会将FooImpl声明为 singleton,因此每次注入时,您都会获得一个新实例。
In case you assumed that this is what @InstallIn(SingletonComponent::class) does, it is not.如果您假设这是@InstallIn(SingletonComponent::class)所做的,那么事实并非如此。 This annotation only tells hilt that FooModule itself should be a singleton and is not scoped to the lifecycle of an Activity, ViewModel or Fragment.这个注解只告诉FooModule本身应该是一个 singleton 并且不局限于 Activity、ViewModel 或 Fragment 的生命周期。

You need to add @Singleton to either FooImpl or the method binding it:您需要将@Singleton添加到FooImpl或绑定它的方法:

Option 1选项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
}

Option 2选项 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.

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