Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Hilt the DI ground running

Hilt the DI ground running

This talk was about Dependency Injection with Hilt at DevFest Egypt. First I explained the concept of Dependency Injection without libraries. Next, I showed how to incorporate Hilt into a new app and how to migrate an existing app.

Moyinoluwa Adeyemi

October 17, 2020
Tweet

More Decks by Moyinoluwa Adeyemi

Other Decks in Programming

Transcript

  1. What is Dependency Injection? “dependency injection is a technique in

    which an object receives other objects that it depends on” According to good ol’ wikipedia
  2. No Dependency Injection class RoboGardener { fun waterPlant() { val

    waterSource = WaterSource() waterSource.dispenseWater() } }
  3. Dependency Injection - Constructor class RoboGardener(private val waterSource: WaterSource) {

    fun waterPlant() { waterSource.dispenseWater() } } fun main() { val roboGardener = RoboGardener(CupOfWater()) roboGardener.waterPlant() }
  4. Dependency Injection - Setter class RoboGardener { lateinit var waterSource:

    WaterSource fun waterPlant() { waterSource.dispenseWater() } }
  5. Dependency Injection - Setter class RoboGardener { lateinit var waterSource:

    WaterSource fun waterPlant() { waterSource.dispenseWater() } } fun main() { val roboGardener = RoboGardener() roboGardener.waterSource = WateringCan() roboGardener.waterPlant() }
  6. Dependency Injection - Interface interface WaterSourceManager { fun provideWaterSource(waterSource: WaterSource)

    } class RoboGardener() : WaterSourceManager { private lateinit var waterSource: WaterSource override fun provideWaterSource(waterSource: WaterSource) { this.waterSource = waterSource } ...
  7. Dependency Injection - Interface interface WaterSourceManager { fun provideWaterSource(waterSource: WaterSource)

    } class RoboGardener() : WaterSourceManager { private lateinit var waterSource: WaterSource override fun provideWaterSource(waterSource: WaterSource) { this.waterSource = waterSource } fun waterPlant() { waterSource.dispenseWater() } } fun main() { val roboGardener = RoboGardener() roboGardener.provideWaterSource(Hose()) roboGardener.waterPlant() }
  8. Service Locators class RoboGardener { fun waterPlant() { val waterSource

    = CupOfWater() waterSource.dispenseWater() } }
  9. Dependency Injection - Dagger Dagger Code generation Steep learning curve

    For Java or Kotlin developers Useful for large projects
  10. @AndroidEntryPoint class MainActivity : AppCompatActivity() { @Inject lateinit var imageLoader:

    ImageLoader private val viewModel: HiltSampleViewModel by viewModels() ... @AndroidEntryPoint
  11. @AndroidEntryPoint @AndroidEntryPoint class MainActivity : AppCompatActivity() { @Inject lateinit var

    imageLoader: ImageLoader private val viewModel: HiltSampleViewModel by viewModels() ...
  12. Scoping - Unscoped bindings @Module @InstallIn(ApplicationComponent::class) abstract class AppModule {

    @Binds abstract fun bindImageLoader(imageLoader: GlideImageLoader): ImageLoader ...
  13. Scoping - Scoped bindings @Module @InstallIn(ApplicationComponent::class) abstract class AppModule {

    @Singleton @Binds abstract fun bindImageLoader(imageLoader: GlideImageLoader): ImageLoader ... ✅
  14. Scoping - Scoped bindings @Module @InstallIn(ApplicationComponent::class) abstract class AppModule {

    @ActivityRetainedScoped @Binds abstract fun bindImageLoader(imageLoader: GlideImageLoader): ImageLoader ... ❌
  15. Scoping - Predefined qualifiers class HiltSampleRepositoryImpl @Inject constructor( @ActivityContext private

    val context: Context, private val hiltSampleService: HiltSampleService ) : HiltSampleRepository {
  16. Multi-module apps - Feature modules “Hilt cannot process annotations in

    feature modules. You must use Dagger to perform dependency injection in your feature modules” Hilt + Dagger
  17. Multi-module apps - Feature modules 1. Install an Entry Point

    in the Application Component from the app module
  18. Multi-module apps - Feature modules 1. Install an Entry Point

    in the Application Component from the app module @EntryPoint @InstallIn(ApplicationComponent::class) interface ImageFeatureModule { fun imageLoader(): ImageLoader }
  19. Multi-module apps - Feature modules 2. In the feature module,

    create a regular dagger component @Component(dependencies = [ImageFeatureModule::class]) interface ImageFeatureComponent { fun inject(activity: ImageFeatureModuleActivity) @Component.Builder interface Builder { fun dependencies(imageFeatureModule: ImageFeatureModule): Builder fun build(): ImageFeatureComponent } }
  20. Multi-module apps - Feature modules 3. Inject the dependency in

    the feature module class ImageFeatureModuleActivity : AppCompatActivity() { @Inject lateinit var imageLoader: ImageLoader @AndroidEntryPoint
  21. Multi-module apps - Feature modules 3. Inject the dependency in

    the feature module ... override fun onCreate(savedInstanceState: Bundle?) { DaggerImageFeatureComponent.builder() .dependencies( EntryPointAccessors.fromApplication( applicationContext, ImageFeatureModule::class.java ) ) .build() .inject(this)
  22. Multi-module apps - Feature modules 3. Inject the dependency in

    the feature module ... override fun onCreate(savedInstanceState: Bundle?) { DaggerImageFeatureComponent.builder() .dependencies( EntryPointAccessors.fromApplication( applicationContext, ImageFeatureModule::class.java ) ) .build() .inject(this)
  23. Resources • Dependency injection with Hilt • Dagger Hilt •

    Using Hilt in your Android app Codelab • Migrating your Dagger app to Hilt Codelab • Scoping in Android and Hilt. Scoping an object A to another object B… | by Manuel Vivo | Android Developers • Hilt in multi-module apps • https://github.com/moyheen/HiltSampleApplication • Image by Gerd Altmann from Pixabay