【问题标题】:Using koin in Multi-module application在多模块应用程序中使用 koin
【发布时间】:2019-10-31 12:37:48
【问题描述】:

嗨,在一个多模块应用程序中,我正在使用 loadKoinModules() 加载子模块并在功能模块中使用 unloadKoinModules() 卸载它,我的代码看起来像

class FeatureActivity:AppCompatActivity(){
    private val loadFeatures by lazy { loadKoinModules(featureModule) }
    private fun injectFeatures() = loadFeatures

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

   override fun onDestroy() {
        super.onDestroy()
        unloadKoinModules(featureModule)
    }
} 

一切正常,但是当加载相同活动的另一个实例时问题开始了。当前活动在后台时。由于以下错误导致应用崩溃

org.koin.error.BeanOverrideException:  Try to override definition with Factory

有没有办法避免这个错误

【问题讨论】:

  • 我正在尝试构建一个模块化应用程序,其中功能模块包含一个活动。该活动可以再次将自身加载为新实例。在这种情况下,我们得到 org.koin.error.BeanOverrideException: Try to override definition with Factory。

标签: android kotlin dependency-injection multi-module koin


【解决方案1】:

您所做的事情在某种程度上是正确的,您可以在执行此操作时动态卸载这就是添加 unloadKoinModules 的原因 link

但是你为什么不卸载onStop?根据android生命周期和你想做什么,你必须unload in onStop

当活动获得焦点onCreate 将发生(并且您将加载模块),稍后当活动失去焦点时,将发生onStop(并且您将卸载模块)并且事件之间的循环......

class FeatureActivity:AppCompatActivity(){
    private val loadFeatures by lazy { loadKoinModules(featureModule) }
    private fun injectFeatures() = loadFeatures

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

   override fun onStop() {
        super.onStop()
        unloadKoinModules(featureModule)
    }
} 

【讨论】:

  • 这不是我正在寻找的解决方案。将 twitter 个人资料页面视为一个功能模块 Activity,您可以从一个个人资料页面导航到另一个。这意味着您需要创建该活动的另一个实例。现在在这种情况下如何加载和卸载模块。
  • 但您的问题是您的工作流程,目前您正尝试在不正确的生命周期状态下加载/卸载。您还可以定义 featureModule 以在每次创建时覆盖它,或者不卸载模块,卸载的概念是重新加载,但在您的情况下看起来并不像您想要的那样
【解决方案2】:

Koin 不会让你重新定义已经存在的定义(type,name,path ...​)。你会遇到错误。

你需要allow definition override:-

val featureModule = module {

    // override for this definition
    single<yourType>(override=true) { YourClass() }
}

您还可以在模块级别覆盖而不是仅在定义级别覆盖:-

val featureModule = module(override=true) {

    single<yourType> { YourClass() }
}

重要:- 列出模块和覆盖定义时,顺序很重要。你必须在你的模块列表的最后有你的覆盖定义。

【讨论】:

【解决方案3】:

一些可能性:

  • 在顶级应用程序级别加载您的功能模块,不要将其范围限定为任何活动生命周期。

  • 在模块加载/卸载周围添加一个引用计数包装器,这样如果模块已经加载,则不会重新加载,并且仅在使用计数为零时才卸载。 (您可以通过不关心卸载并将计数更改为“初始化”布尔值来简化此操作。)

【讨论】:

  • 是的,但这看起来不是解决问题的好方法。目前我正在使用第一点和第二点中提到的混合形式的方法。但需要更好的方法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-22
  • 1970-01-01
  • 2011-04-16
  • 1970-01-01
  • 2017-06-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多