-2

Hello I am working on Android app development and in it a koin dependency injection library is integrated. It is something like below:

object Jaimin {
   fun initJaimin(
        application : Application,
        listOf : List<Module>? = null
    ) {


        var moduleList = listOf(
            jaiminAppModelModule, jaiminBleNetworkModule,
            jaiminViewModelModule, databaseModule,jaiminRepositoryModule
        )

        listOf?.forEach {
            moduleList = moduleList + it
        }

        startKoin {
            androidLogger(if (BuildConfig.DEBUG) Level.ERROR else Level.NONE)
            androidContext(application)
            modules(
                moduleList
            )
        }

    }

You can check startKoin is implemented there. I am getting error here in this module:

val jaiminRepositoryModule = module {
    single {
        JaiminRepository(get(),get())
    }
}

Error:

Instance creation error : could not create instance for [Singleton:'com.jaimin.sdk.repository.JaiminRepository']: org.koin.core.error.NoBeanDefFoundException: |- No definition found for class:'com.jaimin.api.RemoteDataSource'. Check your definitions! org.koin.core.scope.Scope.throwDefinitionNotFound(Scope.kt:287) org.koin.core.scope.Scope.resolveValue(Scope.kt:257)

What might be the issue?

Edit: Below is the constructor for JaiminRepository class:

  class JaiminRepository constructor(
    private var remoteDataSource : RemoteDataSource,
    private var enrollApiInterface : EnrollApiInterface
) {

and

Below is the constructor for JaiminViewModel class:

class JaiminViewModel(application : Application, private var jaiminRepository: JaiminRepository) :
    AndroidViewModel(application) {
    var jaiminEnroll : MutableLiveData<JaiminEnroll> = MutableLiveData()
    var error : MutableLiveData<String> = MutableLiveData()
    var inputUserID : ObservableField<String> = ObservableField("")
    var isLoading : ObservableField<Boolean> = ObservableField(false)

and inside ViewModelModule.kt :

  viewModel {
       JaiminViewModel(get(),get())
    }
Jaimin Modi
  • 1,530
  • 4
  • 20
  • 72
  • When you provide definition for `JaiminRepository`, you'll also need to define singleton or factory instances for it's inner dependencies. I.e. `RemoteDataSource` is not found hence you'll need to create definition for it and then you can use it using `get()` inside repository injection. – Jeel Vankhede Feb 08 '23 at 17:42
  • Can you please explain? It looks little bit confusing from my side. – Jaimin Modi Feb 09 '23 at 05:37

1 Answers1

1

Your biggest issue is that you're not providing definitions correctly.

When you write get(), that means Koin tries to find relevant dependency for that given scope. If it’s not able to find it, then you'll get error org.koin.core.error.NoBeanDefFoundException.

If you look closely to given error:

Instance creation error : could not create instance for [Singleton:'com.jaimin.sdk.repository.JaiminRepository']: org.koin.core.error.NoBeanDefFoundException: |- No definition found for class:'com.jaimin.api.RemoteDataSource'. Check your definitions! org.koin.core.scope.Scope.throwDefinitionNotFound(Scope.kt:287) org.koin.core.scope.Scope.resolveValue(Scope.kt:257)

You'll see that it gives error on RemoteDataSource, hence it was not able to find relevant dependency for that.


The solution is to resolve those dependencies via definitions.

Here's how your DI for repository should look like:

val jaiminRepositoryModule = module {

    factory {
        RemoteDataSource()
    }

    factory<EnrollApiInterface> {
        // Your bean definition for EnrollApiInterface since you can't create objects for interface
    }
    
    single {
        JaiminRepository(get(), get())
    }
}

Same goes for view model dependency:

viewModel {
   JaiminViewModel(androidContext(), get()) // Here, android context can be used to inject application class
}
Jeel Vankhede
  • 11,592
  • 2
  • 28
  • 58
  • Need to change anything here: ? viewModel { JaiminViewModel(get(),get()) } – Jaimin Modi Feb 09 '23 at 08:39
  • Yes, all those `get()` should have it’s own definition that Koin can resolve. – Jeel Vankhede Feb 09 '23 at 13:08
  • But its there...already. one is for application context & other is for repository. – Jaimin Modi Feb 10 '23 at 04:35
  • As you can see above JaiminRepository has two values 1. RemoteDataSource & 2. EnrollApiInterface. I have added factory {} for RemoteDataSource, How to add it for interface named EnrollApiInterface ? – Jaimin Modi Feb 10 '23 at 04:42
  • EnrollApiInterface is an interface. While writing factory for it, displays "Required EnrollApiInterface, found Unit" – Jaimin Modi Feb 13 '23 at 09:26
  • You'll need implementer for that interface. You can’t provide definitions for interfaces directly. So, create one implementer and use it on this DI definition. I.e. `EnrollApiInterfaceImpl` class that implements this interface. – Jeel Vankhede Feb 13 '23 at 09:29
  • I have created implementer but I have no idea what to return from the method. – Jaimin Modi Feb 15 '23 at 08:24