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

aiu*_*eoH 7 android kotlin koin

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

无论这两个模块需要孝允的DI,所以我呼吁startKoinMyApplication类应用模块,并IninKointContentProvider在LIB模块如下。

// 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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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.
Run Code Online (Sandbox Code Playgroud)

我猜startKoin只能叫一次。

我找到的解决方案是合并两个 koin 模块然后调用startKoinin MyApplication,但我不喜欢它。库模块可以通过不使用科因,在这种情况下,其他的Android项目导入,我想呼吁startKoinInitKoinContentProvider是更好的。

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

aiu*_*eoH 7

我受@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()
}
Run Code Online (Sandbox Code Playgroud)

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


laa*_*lto 5

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

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


Ant*_*hev 2

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