shalafi
shalafi

Reputation: 3996

Injecting via a factory when constructor has parameters in toothpick

I have a class that I want to inject which has a constructor that receives one parameter (Context).

I would normally bind it to an instance, but this class has JNI dependencies and I can not instantiate it using Robolectric, which is preventing me from testing the part of the app when the module in configured.

I have set it up as binding to the class and I have annotated the target class as singleton and also the constructor as inject, but it does not construct a factory for it.

I'll be happy to provide my own factory, but I can't find anything about that on the documentation.

This is the part when I do the binding:

val module = Module()        
module.bind(Interface::class.java).to(InterfaceImpl::class.java)
scope.installModules(module)

And this is the way I have set up the class:

@Singleton
class InterfaceImpl : Interface {

   @Inject
   constructor(applicationContext: Context) {
      [...]
   }
}

Just to be clear, if I use toInstance when I do the binding it does work.

val module = Module()        
module.bind(Interface::class.java).toInstance(InterfaceImpl(context))
scope.installModules(module)

How can I get the injected constructor working to bind it to the class?

Upvotes: 1

Views: 1173

Answers (2)

SomeModule(getContext())

bind(Context::class.java).toInstance(context)
bind(InterfaceImpl::class.java).singletonInScope()
bind(Interface::class.java).toProvider(InterfaceProvider::class.java).providesSingletonInScope()

class InterfaceProvider @Inject constructor(private val impl: InterfaceImpl) : Provider<Interface> {
        override fun get(): Interface{
            return impl
        }}

Upvotes: 0

shalafi
shalafi

Reputation: 3996

I found a way. The documentation is a bit lacking.

I can bind it using a provider instance:

val module = Module()
module.bind(Interface::class.java).toProviderInstance(InterfaceProvider(this))
scope.installModules(module)

And then have the InterfaceProvider like this:

class InterfaceProvider (private val context: Context): Provider<Interface> {

    companion object {
        private var instance: Interface? = null
    }

    override fun get(): Interface {
        if (instance == null) {
            instance = InterfaceImpl(context)
        }
        return instance!!
    }
}

Or in an even simpler way, using lambdas in Kotlin:

val module = Module()
module.bind(Interface::class.java).toProviderInstance {
    InterfaceImpl(this)
}.providesSingletonInScope()

Upvotes: 1

Related Questions