sunghun
sunghun

Reputation: 1424

Toothpick doesn't inject dependencies

I am trying Toothpick library for Dependency Injection and it looks easier to use and testable than other ones.

But I am facing an issue when I run the code, Toothpick doesn't inject anything. I am just using it now and it is bit hard to figure out.

I am using Kotlin, Android Studio 2.3.3 and Gradle 2.3.3 and here are my code:

build.gradle

//KOTLIN_VERSION=1.1.4
//TOOTHPICK_VERSION=1.0.8

compile "com.github.stephanenicolas.toothpick:toothpick-runtime:$TOOTHPICK_VERSION"
    compile "com.github.stephanenicolas.toothpick:smoothie:$TOOTHPICK_VERSION"
    kapt "com.github.stephanenicolas.toothpick:toothpick-compiler:$TOOTHPICK_VERSION"


class AppModule : Module {
    constructor(application: Application) {
        bind(QuestionRepository::class.java).toInstance(QuestionRepository(application))
    }
}

class MyApp : Application() {

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

    fun setupInjector() {
        val appScope = Toothpick.openScope(this)
        appScope.installModules(SmoothieApplicationModule(this), AppModule(this))

        if (BuildConfig.DEBUG) {
            Toothpick.setConfiguration(Configuration.forDevelopment());
        }
    }
}

class MainViewModule : Module {
    constructor() {
        bind(MainPresenter::class.java).to(MainPresenter::class.java)
    }
}

class QuestionRepository @Inject constructor(application: Application) {
    val assetManager: AssetManager = application.assets
    
    //a couple of functions
}

class MainActivity : AppCompatActivity(), MainView,
        NavigationView.OnNavigationItemSelectedListener {

    @Inject lateinit var presenter: MainPresenter

    lateinit private var activityScope: Scope

    val binding: ActivityMainBinding by lazy {
        DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
    }

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

    override fun onDestroy() {
        Toothpick.closeScope(activityScope)
        super.onDestroy()
    }

    fun setUpInject() {
        activityScope = Toothpick.openScopes(application, this)
        activityScope.installModules(MainViewModule())
        Toothpick.inject(this, activityScope)

        //println(activityScope.toString())

        presenter.onAttachView(this)
    }

    fun setUpView() {
        //
    }

    //Omit implemented method of OnNavigationItemSelectedListener
}

class MainPresenter @Inject constructor() {}

Error message:

kotlin.UninitializedPropertyAccessException: lateinit property presenter has not been initialized

It displays when I print activityScope in MainActivity:

 Providers: [com.ispark.app.MainPresenter,toothpick.Scope]

When I checked the KotlinWeather example, the code doesn't have install any module in activities but still inject dependencies. I don't get it how it works. Anyway, I am quite new to Toothpick and what am I missing?

Thanks for your helps.

Edit1:

In build.gradle, I replace kapt with annotationProcessor "com.github.stephanenicolas.toothpick:toothpick-compiler:$TOOTHPICK_VERSION" but still same.

Is there any possible issue with AndroidBinding library?

Edit2:

activityScope log was not for activityScope but it was log from Toothpick. activityScope was activityScope:com.ispark.app.MainActivity@2a0e3388:303497268

Upvotes: 1

Views: 1984

Answers (1)

kingargyle
kingargyle

Reputation: 1239

You need to make sure you called Toothpick.inject(this, scope), in your code that is using the presenter. It would also help to have some examples of the code your are using. I also recommend checking out the sample code for the toothpick project, it should get you going. You will also need to either create the scope, or retrieve an existing scope to use for the injection.

Upvotes: 1

Related Questions