3

I learn kodein lib for dependency injection just now. How i can take dependency value for variable? My application class below, there i bind context with kodein:

class BaseApp : Application(), KodeinAware {
    override val kodein by Kodein.lazy {
        import(contextModule)
    }

    private val contextModule = Kodein.Module(CONTEXT_MODULE_TAG){
        bind<Context>(CONTEXT_TAG) with provider { this@BaseApp }
    }

    companion object{
        private const val CONTEXT_MODULE_TAG = "context_module"
        const val CONTEXT_TAG = "context_tag"
    }
}

In my repository class, i tried to take context, but not successfully.

class BatteryRepository : KodeinAware {
    override val kodein by kodein()
    private val context by instance<Context>(BaseApp.CONTEXT_TAG)
...

Where kodein() method call error:

Expression 'kodein' cannot be invoked as a function. The function 'invoke()' is not found

How i can get context? Is it good idea to transfer context like that?

UjinUkr
  • 215
  • 5
  • 15

1 Answers1

5

I had the same issue. Turns out that I was missing this dependency import org.kodein.di.android.x.kodein (not sure why it was not automatically added by IDE)

Here is an example of Kodein + AndroidX libraries: AndroidManifest.xml

<application
        ...
        android:name=".core.BaseApplication">

Application

open class BaseApplication : Application(), KodeinAware {
    override val kodein = Kodein.lazy {
        import(androidXModule(this@BaseApplication))

        // import(otherCustomModule)
    }
}

Fragments

import androidx.fragment.app.Fragment
import org.kodein.di.Kodein
import org.kodein.di.KodeinAware
import org.kodein.di.android.x.kodein
import org.kodein.di.generic.kcontext

abstract class InjectionFragment : Fragment(), KodeinAware {

    final override val kodeinContext = kcontext<Fragment>(this)
    final override val kodein: Kodein by kodein()


    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        kodeinTrigger?.trigger()
    }
}

// usage
class MyFragment() : InjectionFragment() {
    val someDependency: Type by instance()
}

Dependencies app\build.gradle

implementation "org.kodein.di:kodein-di-generic-jvm:6.3.2"
implementation "org.kodein.di:kodein-di-framework-android-x:6.3.2"
implementation "androidx.appcompat:appcompat:1.0.2"

Extra It is also worth to override kodeinTrigger property (from KodeinAware). This way all the dependencies for debug builds will be resolved when Fragment is created, so app will fail instantly (as opposed to release builds where dependency is resolved only when it is used - some user paths may not crash the app)

abstract class InjectionFragment : Fragment(), KodeinAware {

    final override val kodeinContext = kcontext<Fragment>(this)
    final override val kodein: Kodein by kodein()
    final override val kodeinTrigger: KodeinTrigger? // See description in InjectionActivity
        get() = if (BuildConfig.DEBUG) KodeinTrigger() else super.kodeinTrigger

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        kodeinTrigger?.trigger()
    }
}

Edit: Here is my project where everything is wired together https://github.com/igorwojda/Android-Showcase

Igor
  • 2,039
  • 23
  • 27
  • 2
    I’d like to add that this import `import org.kodein.di.android.x.kodein` is VERY important. For some reason it never auto imports and i’m on AS v3.5. Thanks for the great answer – Sakiboy Sep 20 '19 at 14:43
  • thank you for this import org.kodein.di.android.x.kodein. it was driving me crazy – kodlan Nov 28 '19 at 18:24
  • This issue has been reported in Kotlin issue tracker https://youtrack.jetbrains.com/issue/KT-33318 Please vote – Igor Nov 29 '19 at 10:47
  • how to inject into a broadcast receiver ? – Sagar Nayak Jan 21 '20 at 08:41