Search code examples
androidkotlindependency-injectiondagger-2

Injecting a interface using variable injection in activity in android


Connection.kt

interface Connection {
    fun connect(endpoint:String)
}

HttpsConnection.kt

class HttpsConnection @Inject constructor(): Connection {

    override fun connect(endpoint: String) {
        PrintUtils.printLog("HttpsConnection made")
    }

}

HttpsConnectionModule.kt

@Module
@DisableInstallInCheck
class `HttpsConnectionModule` {

    @Provides
    fun provideHttpsConnection() : Connection {
        return HttpsConnection()
    }

}

ConnectionComponent.kt

@Component(modules = [HttpsConnectionModule::class])
interface ConnectionComponent {
    fun inject(activity: IntroScopeDemoActivity)
}

IntroScopeDemoActivity.kt

class IntroScopeDemoActivity : AppCompatActivity() {

    //@Inject lateinit var conn : HttpsConnection
    //@Inject lateinit var connInterface : Connection

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_intro_scope_demo)

        val comp = DaggerConnectionComponent.builder().build()
        comp.inject(this@IntroScopeDemoActivity)

        println("Injection completed")

    }
}

What is Happening

@Inject lateinit var conn : HttpsConnection

  • If I use the above code to inject for implementation, it will work

  • But if I use the below line to inject the interface, It doesn't work

@Inject lateinit var connInterface : Connection


Error:

/Users/devrath/Documents/Projects/Github/droid-di-use-cases/frameworks/hilt/code/app/build/tmp/kapt3/stubs/debug/com/istudio/di/modules/dagger/demos/scopes/introdemo/components/ConnectionComponent.java:9: error: [Dagger/MissingBinding] java.sql.Connection cannot be provided without an @Provides-annotated method.
public abstract interface ConnectionComponent {
                ^
      java.sql.Connection is injected at
          com.istudio.di.modules.dagger.demos.scopes.introdemo.IntroScopeDemoActivity.connInterface
      com.istudio.di.modules.dagger.demos.scopes.introdemo.IntroScopeDemoActivity is injected at
          com.istudio.di.modules.dagger.demos.scopes.introdemo.components.ConnectionComponent.inject(com.istudio.di.modules.dagger.demos.scopes.introdemo.IntroScopeDemoActivity)

Question:

Is it possible to inject the interface in the variable since the interface has an implementation-defined and attached in the component as a module?


Solution

    1. Please check the imports in IntroScopeDemoActivity. Looks like @Inject lateinit var connInterface : Connection is from java.sql.Connection instead of your Connection interface.
    2. In this case you don't need @Provides, you can use @Binds instead:
    @Binds
    fun bindHttpsConnection(impl: HttpsConnection): Connection
    

    It works as you've already added HttpsConnection to the graph (with @Inject constructor), and with @Binds you just "map" the implementation to an interface.

    As this method has only a signature and no implementation body, HttpsConnectionModule cannot be a regular class, but can be an interface.