I am converting my whole project into Koin. Using Koin KMP (I am converting right now my shared module).
And I have multiple modules, that are being executed in one main module (which the main contains the references to the others), for organisation proposes only.
Here's my Main Module:
package pt.custojusto.procore.shared.dependencyinjection
import io.ktor.client.HttpClient
import kotlinx.coroutines.CoroutineScope
import kotlinx.serialization.InternalSerializationApi
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import org.koin.core.context.startKoin
import org.koin.dsl.koinApplication
import org.koin.dsl.module
import pt.custojusto.accountprivate.AccountPrivateKoinInitializer
import pt.custojusto.authenticationprivate.AuthenticationKoinInitializer
import pt.custojusto.buyoptions.BuyOptionsKoinInitializer
import pt.custojusto.configuration.ConfigurationKoinInitializer
import pt.custojusto.configuration.firebase.FeatureTogglesFirebaseRemoteConfig
import pt.custojusto.configuration.services.featuretoggles.configuratorapp.FeatureTogglesConfiguratorAppService
import pt.custojusto.global.core.expectations.CJFileManager
import pt.custojusto.global.core.expectations.ChallengeHandler
import pt.custojusto.global.core.expectations.KtorFactory
import pt.custojusto.global.core.models.AppEnvironment
import pt.custojusto.messaging.MessagingSharedKoinInitializer
import pt.custojusto.parametersprivate.ParametersPrivateKoinInitializer
import pt.custojusto.procore.shared.repositories.provider.RepositoryProvider
import pt.custojusto.procore.shared.repositories.provider.RepositoryProviderImpl
import pt.custojusto.procore.shared.services.provider.ServiceProvider
import pt.custojusto.procore.shared.services.provider.ServiceProviderImpl
import pt.custojusto.procore.shared.usecases.provider.UseCaseProvider
import pt.custojusto.procore.shared.usecases.provider.UseCaseProviderImpl
@InternalSerializationApi
class KoinModules : KoinComponent {
lateinit var ktor: HttpClient
val services: ServiceProvider by inject()
val repositories: RepositoryProvider by inject()
val useCases: UseCaseProvider by inject()
val buyOptionsKoinInitializer: BuyOptionsKoinInitializer by inject()
val authenticationKoinInitializer: AuthenticationKoinInitializer by inject()
val configurationKoinInitializer: ConfigurationKoinInitializer by inject()
val parametersPrivateKoinInitializer: ParametersPrivateKoinInitializer by inject()
val accountPrivateKoinInitializer: AccountPrivateKoinInitializer by inject()
val messagingSharedKoinInitializer: MessagingSharedKoinInitializer by inject()
private val servicesModules = module {
single { ServiceProviderImpl(get(), get(), get()) }
single { RepositoryProviderImpl(get(), get(), get()) }
single { UseCaseProviderImpl(get(), get(), get()) }
}
fun initKoin(
coroutineScope: CoroutineScope,
isDebug: Boolean,
fileManager: CJFileManager,
sessionFileUrl: String,
sessionChallengeHandler: ChallengeHandler?,
configuratorAppFeatureTogglesService: FeatureTogglesConfiguratorAppService,
firebaseRemoteConfig: FeatureTogglesFirebaseRemoteConfig,
versionName: String,
versionCode: Int,
isPro: Boolean
) {
this.ktor = KtorFactory.create(sessionChallengeHandler, versionName, versionCode, isPro)
val koinServices = koinApplication {
modules(servicesModules)
}
startKoin {
modules(module {
koinServices
//TODO: Check if initialization works like this on koin
factory {
ConfigurationKoinInitializer(
coroutineScope, configuratorAppFeatureTogglesService, firebaseRemoteConfig
).configurationModule
}
factory {
AuthenticationKoinInitializer(
fileManager,
sessionFileUrl
).authenticationModule
}
BuyOptionsKoinInitializer().buyOptionsModule
ParametersPrivateKoinInitializer(
ktor,
configurationKoinInitializer.configurationService,
authenticationKoinInitializer.sessionRepository
).parametersModule
AccountPrivateKoinInitializer(
ktor,
configurationKoinInitializer.configurationService,
authenticationKoinInitializer.sessionRepository
).accountModule
/*val serviceProvider = ServiceProviderImpl(
configurationKoinInitializer.configurationService,
authenticationKoinInitializer.sessionRepository,
ktor
)
val repositoryProvider = RepositoryProviderImpl(
serviceProvider,
authenticationKoinInitializer.sessionRepository,
accountPrivateKoinInitializer.accountRepository
)*/
MessagingSharedKoinInitializer(
ktor,
services.configurationService,
authenticationKoinInitializer.sessionRepository
).messagingModule
})
}
configureEnvironment(isDebug)
with(services, repositories, useCases)
}
fun with(
serviceProvider: ServiceProvider,
repositoryProvider: RepositoryProvider,
useCaseProvider: UseCaseProvider
) {
}
private fun configureEnvironment(isDebug: Boolean) {
val configuration = repositories.provideConfigurationRepository()
if (configuration.firstLaunch) {
if (isDebug) {
configuration.saveAppEnvironment(AppEnvironment.Qa)
} else {
configuration.saveAppEnvironment(AppEnvironment.Prod)
}
configuration.saveFirstLaunch(false)
}
}
}
Here's the child module, per example ConfigurationKoinInitializer.
package pt.custojusto.configuration
import kotlinx.coroutines.CoroutineScope
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import org.koin.core.context.startKoin
import org.koin.dsl.module
import pt.custojusto.configuration.firebase.FeatureTogglesFirebaseRemoteConfig
import pt.custojusto.configuration.repositories.configuration.ConfigurationRepository
import pt.custojusto.configuration.repositories.configuration.ConfigurationRepositoryImpl
import pt.custojusto.configuration.repositories.featuretoggles.FeatureTogglesRepository
import pt.custojusto.configuration.repositories.featuretoggles.FeatureTogglesRepositoryImpl
import pt.custojusto.configuration.services.configuration.ConfigurationService
import pt.custojusto.configuration.services.configuration.ConfigurationServiceImpl
import pt.custojusto.configuration.services.featuretoggles.FeatureTogglesService
import pt.custojusto.configuration.services.featuretoggles.configuratorapp.FeatureTogglesConfiguratorAppService
import pt.custojusto.configuration.services.featuretoggles.local.FeatureTogglesLocalService
class ConfigurationKoinInitializer(
coroutineScope: CoroutineScope,
configuratorAppFeatureTogglesService: FeatureTogglesConfiguratorAppService,
firebaseRemoteConfig: FeatureTogglesFirebaseRemoteConfig
) : KoinComponent {
val configurationService: ConfigurationService by inject()
val featureTogglesService: FeatureTogglesService by inject()
val configurationRepository: ConfigurationRepository by inject()
val featureTogglesRepository: FeatureTogglesRepository by inject()
val configurationModule = module {
single { coroutineScope }
single { configuratorAppFeatureTogglesService }
single { firebaseRemoteConfig }
single { ConfigurationServiceImpl(get()) }
single { FeatureTogglesLocalService() }
single { ConfigurationRepositoryImpl(get()) }
single {
FeatureTogglesRepositoryImpl(
get(),
get(),
get(),
get()
)
}
}
}
When building the app, it gives me an error about the initialisers, that I have on my KoinModules. I've tried to initialise with the get() (example: configurationKoinInitializer = get() )
and by the normal way we initialise things
(example: configurationKoinInitializer = ConfigurationKoinInitializer(
coroutineScope, configuratorAppFeatureTogglesService, firebaseRemoteConfig
).configurationModule)
But it doesn't work...
The error I get on my Logcat:
ATAL EXCEPTION: main Process: com.schibsted.iberica.custojusto.debug, PID: 6741 java.lang.RuntimeException: Unable to create application
pt.custojusto.MainApplication: org.koin.core.error.NoBeanDefFoundException: No definition found for type 'pt.custojusto.configuration.ConfigurationKoinInitializer'. Check your Modules configuration and add missing type and/or qualifier! at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7619) at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2400) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:226) at android.os.Looper.loop(Looper.java:313) at android.app.ActivityThread.main(ActivityThread.java:8757) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067) Caused by: org.koin.core.error.NoBeanDefFoundException: No definition found for type 'pt.custojusto.configuration.ConfigurationKoinInitializer'. Check your Modules configuration and add missing type and/or qualifier! at org.koin.core.scope.Scope.throwDefinitionNotFound(Scope.kt:301) at org.koin.core.scope.Scope.resolveValue(Scope.kt:271) at org.koin.core.scope.Scope.resolveInstance(Scope.kt:233) at org.koin.core.scope.Scope.get(Scope.kt:212) at pt.custojusto.procore.shared.dependencyinjection.KoinModules$special$$inlined$inject$default$6.invoke(KoinComponent.kt:67) at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74) at pt.custojusto.procore.shared.dependencyinjection.KoinModules.getConfigurationKoinInitializer(KoinModules.kt:41) at pt.custojusto.procore.shared.dependencyinjection.KoinModules$initKoin$1$1.invoke(KoinModules.kt:91) at pt.custojusto.procore.shared.dependencyinjection.KoinModules$initKoin$1$1.invoke(KoinModules.kt:72) at org.koin.dsl.ModuleDSLKt.module(ModuleDSL.kt:45) at org.koin.dsl.ModuleDSLKt.module$default(ModuleDSL.kt:43) at pt.custojusto.procore.shared.dependencyinjection.KoinModules$initKoin$1.invoke(KoinModules.kt:72) at pt.custojusto.procore.shared.dependencyinjection.KoinModules$initKoin$1.invoke(KoinModules.kt:71) at org.koin.core.context.GlobalContext.startKoin(GlobalContext.kt:64) at org.koin.core.context.DefaultContextExtKt.startKoin(DefaultContextExt.kt:40) at pt.custojusto.procore.shared.dependencyinjection.KoinModules.initKoin(KoinModules.kt:71) at pt.custojusto.MainApplication.onCreate(MainApplication.kt:155) at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1266) at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7614)
I am new at dependency injection.
If someone has any idea, I would love.
Thanks.