Skip to content

Dagger ‐ Interface injection

Devrath edited this page Oct 6, 2023 · 5 revisions

Observations

  • Sometimes there are scenarios where we need to inject an interface as field injection or constructor injection.
  • We know that interface does not have a constructor, Now the way we handle it is that we define an implementation of an interface and add @Inject to the implementation for the constructor.
  • If we are injecting the interface in another constructor, We don't need to do anything else but say if the interface has multiple implementations then Dagger will throw an error so we might need to distinguish between the implementations that we are injecting using a @Qualifiers.
  • If we are doing a field injection, then we need to return the interface as the function in the component, and in the parameter of that function, we need to have the implementation class.
  • In the output below you can observe that only one implementation of the interface is invoked since.
  • This gets decided by the module specified in the component class.

Output

ComputerBattery constructor is invoked !
LcdScreen constructor is invoked !
Laptop constructor is invoked !
LcdScreen build screen is invoked !
Laptop is running -> uses <-> kotlin.Unit

Code

implementations

ComputerScreen.kt

interface ComputerScreen {
    fun buildScreen();
}

LcdScreen.kt

class LcdScreen @Inject constructor() : ComputerScreen {

    init { printLog("LcdScreen constructor is invoked !") }

    override fun buildScreen() { printLog("LcdScreen build screen is invoked !") }

}

TftScreen.kt

class TftScreen @Inject constructor() : ComputerScreen {

    init { printLog("LcdScreen constructor is invoked !") }

    override fun buildScreen() { printLog("TftScreen build screen is invoked !") }

}

ComputerBattery.kt

class ComputerBattery @Inject constructor() {

    init { printLog("ComputerBattery constructor is invoked !") }

}

Laptop.kt

class Laptop @Inject constructor( var computerBattery: ComputerBattery, var computerScreen: ComputerScreen ){

    init { printLog("Laptop constructor is invoked !") }

    fun runLaptop() { printLog("Laptop is running -> " +  "uses <-> ${computerScreen.buildScreen()}" ) }

}

Modules

LcdScreenModule.kt

@Module
@DisableInstallInCheck
class LcdScreenModule {

    @Provides
    fun providesLcdScreen(lcdScreen : LcdScreen) : ComputerScreen{
        return lcdScreen;
    }

}

TftScreenModule.kt

@Module
@DisableInstallInCheck
class TftScreenModule {

    @Provides
    fun providesTftScreen(tftScreen : TftScreen) : ComputerScreen {
        return tftScreen;
    }

}

Components

LaptopComponent.kt

@Component(modules = [LcdScreenModule::class])
interface LaptopComponent {
    fun getLaptop() : Laptop

}

Activity

MyActivity

class MyActivity : AppCompatActivity() {

    private lateinit var binding: ActivityDaggerConceptsBinding

    @Inject
    lateinit var mobile : Mobile

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityDaggerConceptsBinding.inflate(layoutInflater)
        setContentView(binding.root)
        setOnClickListener()
    }

    private fun setOnClickListener() {
        binding.apply {
            // Injecting Interface
            injectingInterfaceId.setOnClickListener {
                val laptopComponent = DaggerLaptopComponent.create().getLaptop()
                laptopComponent.runLaptop()
            }
        }
    }
}
Clone this wiki locally