繁体   English   中英

如何在多个模块中使用 Koin?

[英]How to use Koin in multiple module?

我的android项目中有两个模块,app模块和lib模块。

这两个模块都需要 Koin 进行 DI,所以我在 app 模块中调用MyApplication startKoin中的IninKointContentProvider ,在 lib 模块中调用 IninKointContentProvider,如下所示。

// app module
class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        startKoin(this, modules1)
    }
}

// lib module
class InitKoinContentProvider : ContentProvider() {
    override fun onCreate(): Boolean {
        startKoin(context.applicationContext, modules2)
        return true
    }
}

然后应用程序崩溃并显示此消息

Caused by: org.koin.error.BeanOverrideException: Try to override definition with Single [class='android.content.Context'], but override is not allowed. Use 'override' option in your definition or module.

我想startKoin只能调用一次。

我找到的解决方案是合并两个 koin 模块,然后在MyApplication中调用startKoin ,但我不喜欢它。 Lib 模块可能被其他不使用 koin 的 android 项目导入,在这种情况下,我认为在InitKoinContentProvider中调用startKoin更好。

这个问题有什么解决办法吗?? 谢谢!

我找到了受@laalto 回答启发的最佳解决方案,谢谢!

升级到koin 2.0,然后使用KoinApplication和自定义的KoinComponent来创建一个隔离的koin上下文,它可以让lib模块使用koin而无需app模块进行任何初始化调用,仍然在ContentProvider中启动koin。 整个代码可能如下所示。

// app module
class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        startKoin {
            androidContext(this@MyApplication)
            modules(module{
                viewModel { MainViewModel() }
            })
        }
    }
}

class MainActivity: AppCompactActivity() {
    private val viewModel: MainViewModel by viewModel()
}



// lib module
internal object MyKoinContext {
    lateinit var koinApplication: KoinApplication
}

interface MyKoinComponent : KoinComponent {
    override fun getKoin(): Koin {
        return MyKoinContext.koinApplication.koin
    }
}

class InitKoinContentProvider : ContentProvider() {
    override fun onCreate(): Boolean {
        MyKoinContext.koinApplication = koinApplication {
            androidContext(context.applicationContext)
            modules(module{
                viewModel { FooViewModel() }
            })
        }
        return true
    }
}

class FooActivity: AppCompactActivity(), MyKoinComponent {
    private val viewModel: FooViewModel by viewModel()
}

参考: https : //insert-koin.io/docs/2.0/documentation/reference/index.html#_koin_context_isolation

要在其他项目模块上初始化额外的 koin 模块并且不会出现重复的加载问题(例如按下主页,而不是返回活动),请转到您的模块声明文件:

val myModule = module {
    single { MyRepository(get()) }
    viewModel { MyViewModel(get()) }
}

private val loadKoinModules by lazy {
    loadKoinModules(myModule)
}

fun inject() = loadKoinModules

那么在你看来:

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

TL;DR 在提供覆盖之前加载的模块提供的依赖项时,使用override参数设置为true single/factory方法。

single<Manager>(override = true) { TestManager() }

当我为了 UI 测试目的而尝试覆盖其中一个依赖项时,我遇到了类似的问题。 当我在Application.onCreate()设置时:

startKoin {
   module {
       single { Printer() }
   }
}

然后在测试方法before

loadKoinModules(module {
    single<Printer> { TestPrinter() }
})

我在测试期间收到运行时异常: org.koin.core.error.DefinitionOverrideException: Already existing definition or try to override an existing one

解决方案是向 Koin 展示您有意通过使用single函数的override参数来override该依赖项,如下所示:

loadKoinModules(module {
    single<Printer>(override = true) { TestPrinter() }
})

在您的库模块中,使用loadKoinModules()加载特定于模块的 koin 模块。 文档

您需要在此之前运行startKoin() ,因此内容提供程序的初始化顺序可能有点棘手。

根据设计, startKoin旨在从 Application 类中调用。 你可以在lib中提供一个参数是否调用startKoin 但我怀疑在 libs 中包含 Koin 之类的东西是一种很好的做法。 如果应用程序已经包含 Koin,但版本不同怎么办?

这种方式对我来说很完美:

@KoinExperimentalAPI 
class MainApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        initKoin()
    }

    private fun initKoin() {
        startKoin {
            androidLogger()
            androidContext(this@MainApplication)
        }
        loadKoinModules(
            myFeatureModule
        )
    }
}

并像往常一样在您的功能中定义您的模块:

val myFeatureModule = module {
    factory<...> { ...() }

    single { ...() }

    viewModel { ...(get() }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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