【问题标题】:Koin how to inject outside of Android activity / appcompatactivityKoin 如何在 Android 活动 / appcompatactivity 之外注入
【发布时间】:2018-04-03 11:50:13
【问题描述】:

Koin 是一个新的轻量级 DI 库,可用于 Android 以及独立的 kotlin 应用程序。

通常你像这样注入依赖:

class SplashScreenActivity : Activity() {

    val sampleClass : SampleClass by inject()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }
}

使用inject() 方法。

但是在 Activity 上下文不可用的地方(即 Activity 之外)注入东西呢?

【问题讨论】:

  • 您找到解决方案了吗?我也面临同样的问题

标签: android dependency-injection kotlin inversion-of-control koin


【解决方案1】:

KoinComponent 来救援。在任何课程中,您都可以:

class SampleClass : KoinComponent {

    val a : A? by inject()
    val b : B? by inject()
}

扩展KoinComponent 使您可以访问inject() 方法。

请记住,通常以通常的方式注入东西就足够了:

class SampleClass(val a : A?, val b: B?)

【讨论】:

  • 你确定你的A类和B类可以有空值吗?
  • 嗯,我认为从 KISS 的角度来看,在这种情况下最好使用构造函数(不要过度设计事物;))作为注入点。但有趣的是,我们可以扩展 Koin component 以允许使用 Koin 进行注入。
  • 你是说在这种情况下我们不需要startKoin
  • 请注意,如果不是绝对必要,不应使用 KoinComponent:“我看到的另一件事是滥用 KoinComponent 接口来扩展服务定位器 API。请注意,作为 Koin 框架用户,你应该不需要使用这个接口。”medium.com/koin-developers/…
【解决方案2】:

Koin 使用KoinComponent 接口为此提供了一个解决方案。例如,如果您需要在存储库中获取一些依赖项,那么您可以简单地实现 KoinComponent 接口。它使您可以访问各种 Koin 功能,例如 get()inject()。仅当您无法重写构造函数以接受依赖项作为构造函数参数时才使用 KoinComponent。

class MyRepository: Repository(), KoinComponent {
  private val myService by inject<MyService>()
}

构造函数注入比这种方法更好。

例如,同样的事情可以通过:

class MyRepository(private val service: MyService): Repository() {
    ...
}

您可以在 koin 模块中添加用于实例化此类的定义:

val serviceModule = module {
    ...

    factory { MyService() }
}
val repositoryModule = module {
    ...

    factory { MyRepository(get<MyService>()) }
}

【讨论】:

  • 为什么构造函数注入比使用 KoinComponent 的方法更好?
  • 使用 KoinComponent 的方法称为字段注入。以下是构造函数注入更好的几个原因: 1. 更简单:你的类只关心它需要什么依赖项,而不关心谁满足它们。 2. 更健壮:你的类的一个实例一被构造就处于一致的状态,而不是在字段注入完成之后。 3. 更轻松的测试:在构造函数中声明依赖关系可以更轻松地在测试时提供模拟。
  • @harold_admin 很好的答案,你能解释一下我们在这里扩展/实现的“Repository()”是什么吗?
  • @Hatzil 它可以是任何基类。老实说,对于这个例子的目的来说,这并不重要。我只是想说明,不管你有没有基类,你都可以使用 Koin。
  • 嘿@harold_admin 很好的答案,还有一个问题,如果“MyRepository”是一个清单声明的广播接收器呢?我已经通过使用 koin injection 扩展解决了这个问题,但也许还有另一种解决方案?
【解决方案3】:

如果您不想实现任何接口,那么只需看看KoinComponent.inject() 是如何实现的,然后自己做类似的事情:

val foo by lazy { KoinPlatformTools.defaultContext().get().get<FooClass>() }

【讨论】:

  • 如果您想从 ApplicationClass 本身访问由 koin 配置的内容,则特别有用 :)
猜你喜欢
  • 2019-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-19
  • 1970-01-01
相关资源
最近更新 更多