android - 使用带有挂起功能 block 的接口(interface)类的 Hilt 进行依赖注入(inject)

标签 android kotlin kotlin-coroutines dagger-hilt

我声明了一个使用挂起函数的类。这个类是由 Hilt 库在 Android 上注入(inject)的单例依赖项:

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
 }

然后,如果当我调用接收函数时,它会永远被阻止。未收到数据,示例:

@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 是一个单例,我可以实现一个简单的解决方法。如果 Foo 在 Hilt 中以这种方式实现,我就没有问题:

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

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

我想知道这是 Hilt bug 还是我的 FIRST_CASE hilt 模块实现错误?

最佳答案

您永远不会将 FooImpl 声明为单例,因此每次注入(inject)它时,您都会获得一个新的实例。
如果您认为这就是 @InstallIn(SingletonComponent::class) 的作用,则事实并非如此。此注释仅告诉 hilt FooModule 本身应该是单例,并且范围不限于 Activity、ViewModel 或 Fragment 的生命周期。

您需要将 @Singleton 添加到 FooImpl 或绑定(bind)它的方法:

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

关于android - 使用带有挂起功能 block 的接口(interface)类的 Hilt 进行依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71508563/

相关文章:

android - 在 Android 上使用 librtmp 编译 FFMPEG 时出现 "Undefined Reference"

java - Android查询关于onClick和android控制流程

android - 单击 fragment 中的工具栏菜单项 (Kotlin)

kotlin - 为什么每个线程都会多次初始化惰性变量

Kotlin 协程 - 如何在后台运行并在调用者线程中使用结果?

java - 如何检测将要删除的内容

java - Android 的特定设备检测?

exception - Kotlin - 异常后继续协程

kotlin - 是否可以暂停协程并超时?

android - 当 CoroutineScope 被取消时,Coroutine StateFlow 停止发射