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

Dagger 2 Android : Defeat the Dahaka

A3958eeb9a7f402b134c0c017d6614ee?s=47 ragdroid
September 03, 2017

Dagger 2 Android : Defeat the Dahaka

Presentation for Droidcon Berlin, 2017.

Github Demo : https://github.com/ragdroid/Dahaka
Medium Blogs : https://proandroiddev.com/dagger-2-android-defeat-the-dahaka-b1c542233efc

A3958eeb9a7f402b134c0c017d6614ee?s=128

ragdroid

September 03, 2017
Tweet

Transcript

  1. “Defeat the Dahaka" Dagger 2 Android Garima Jain @ragdroid

  2. Garima Jain @ragdroid

  3. Garima Jain @ragdroid

  4. Garima Jain @ragdroid

  5. Garima Jain @ragdroid

  6. Garima Jain @ragdroid

  7. Garima Jain @ragdroid

  8. @ragdroid @droidconDE

  9. @ragdroid @droidconDE MVP Testing DataBinding Retrofit Dagger 2

  10. Garima Jain @ragdroid “Defeat the Dahaka" Dagger 2 Android

  11. @ragdroid @droidconDE POP QUIZ • Dagger2? • Dagger Android •

    Prince of Persia
  12. ABOUT THE TALK

  13. Theme: Prince of Persia • Prince uses Dagger • Dagger

    can reverse time • Dahaka, (guardian of timeline) • Dahaka comes to kill the Prince.
  14. Analogy • Prince = Us • Dagger = Dagger •

    Dahaka (Enemy) = Generated Code, Complexity
  15. Analogy • Developer uses Dagger • Developer starts backtracking the

    generated code • Developer is chased by the Dahaka (complexity of generated code)
  16. Agenda • Brief Introduction - “Codes of Time” • Scopes

    - “Face of the Dahaka” • @Singleton Scopes • @Reusable Scopes • Custom Scopes • Component Dependencies - “Unleash the Beast” • Demo App • Dependent Component • Subcomponent • Intermediate Concepts - “Defeat the Dahaka” • Dagger Android - “Befriend the Beast”
  17. Who? • Assumption : Basic familiarity with Dagger • Intermediate

  18. INTRODUCTION “CODES OF TIME”

  19. @ragdroid @droidconDE Droid of Asia

  20. @ragdroid @droidconDE public UserManager() {
 this.service = new PokemonService(); 


    } Droid of Asia
  21. @ragdroid @droidconDE Dependency Creation Disadvantages • Non-Testable • Non-Extendable

  22. @ragdroid @droidconDE Dagger 1

  23. @ragdroid @droidconDE Dagger 1 Advantages • Testable code • Modularized

  24. @ragdroid @droidconDE Dagger 1 Disadvantages • Reflection • Runtime Graph

    Composition • God Module with @Singleton • Difficult to use proguard
  25. @ragdroid @droidconDE Dagger 1 Disadvantages Dagger 2

  26. @ragdroid @droidconDE Dagger 2 Advantages • No Reflection • Compile-time

    Graph Composition • Traceable code • Better Scope management
  27. SCOPES “FACE OF THE DAHAKA”

  28. Scope • Annotation from javax.inject package • How long a

    scoped instance lives • What happens if : • No Scope specified? • Annotation is specified?
  29. @Singleton • Another annotation from javax.inject package • Scope of

    dependency is throughout the application • Two ways to re-use dependencies : • Annotate Provider methods • Annotate the Dependency class itself
  30. @ragdroid @droidconDE @SINGLETON EXAMPLE

  31. AppComponent @Component(modules = AppModule.class) @Singleton public interface AppComponent { Application

    application(); }
  32. AppComponent @Component(modules = AppModule.class) @Singleton public interface AppComponent { Application

    application(); } AppComponent
  33. @ragdroid @droidconDE CASE 1 DEPENDENCY W/O SCOPE

  34. AppModule @Module public class AppModule { private final Application application;

    public AppModule(Application application) { this.application = application; } @Provides //No @Singleton annotation Application applicationProvider() { return application; } }
  35. @Module public class AppModule { private final Application application; public

    AppModule(Application application) { this.application = application; } @Provides //No @Singleton annotation Application applicationProvider() { return application; } } AppModule
  36. DaggerAppComponent @Generated public final class DaggerAppComponent implements AppComponent { private

    Provider<Application> applicationProvider; /** other code **/ private void initialize(final Builder builder) { this.applicationProvider = AppModule_ApplicationFactory.create(builder.appModule); } } (Generated)
  37. DaggerAppComponent @Generated public final class DaggerAppComponent implements AppComponent { private

    Provider<Application> applicationProvider; /** other code **/ private void initialize(final Builder builder) { this.applicationProvider = AppModule_ApplicationFactory.create(builder.appModule); } } (Generated)
  38. DaggerAppComponent @Generated public final class DaggerAppComponent implements AppComponent { private

    Provider<Application> applicationProvider; /** other code **/ private void initialize(final Builder builder) { this.applicationProvider = AppModule_ApplicationFactory.create(builder.appModule); } } (Generated)
  39. @ragdroid @droidconDE CASE 2 DEPENDENCY WITH SCOPE

  40. AppModule @Module public class AppModule { private final Application application;

    public AppModule(Application application) { this.application = application; } @Provides @Singleton Application applicationProvider() { return application; } }
  41. AppModule @Module public class AppModule { private final Application application;

    public AppModule(Application application) { this.application = application; } @Provides @Singleton Application applicationProvider() { return application; } }
  42. DaggerAppComponent @Generated public final class DaggerAppComponent implements AppComponent { private

    Provider<Application> applicationProvider; /** other code **/ private void initialize(final Builder builder) { this.applicationProvider = DoubleCheck.provider( AppModule_ApplicationFactory.create(builder.appModule)); } } (Generated)
  43. DaggerAppComponent @Generated public final class DaggerAppComponent implements AppComponent { private

    Provider<Application> applicationProvider; /** other code **/ private void initialize(final Builder builder) { this.applicationProvider = DoubleCheck.provider( AppModule_ApplicationFactory.create(builder.appModule)); } } (Generated)
  44. DaggerAppComponent @Generated public final class DaggerAppComponent implements AppComponent { private

    Provider<Application> applicationProvider; /** other code **/ private void initialize(final Builder builder) { this.applicationProvider = DoubleCheck.provider( AppModule_ApplicationFactory.create(builder.appModule)); } } (Generated)
  45. DaggerAppComponent @Generated public final class DaggerAppComponent implements AppComponent { private

    Provider<Application> applicationProvider; /** other code **/ private void initialize(final Builder builder) { this.applicationProvider = DoubleCheck.provider( AppModule_ApplicationFactory.create(builder.appModule)); } } (Generated)
  46. DoubleCheck Memoizes value using Double-Check idiom. (dagger.internal)

  47. DoubleCheck Memoizes value using Double-Check idiom. public T get() {


    Object result = instance;
 if (result == UNINITIALIZED) {
 synchronized (this) {
 result = instance;
 if (result == UNINITIALIZED) {
 result = provider.get();
 
 Object currentInstance = instance; // other code
 instance = result;
 
 provider = null;
 }
 }
 }
 return (T) result;
 } (dagger.internal)
  48. DoubleCheck Memoizes value using Double-Check idiom. public T get() {


    Object result = instance;
 if (result == UNINITIALIZED) {
 synchronized (this) {
 result = instance;
 if (result == UNINITIALIZED) {
 result = provider.get();
 
 Object currentInstance = instance; // other code
 instance = result;
 
 provider = null;
 }
 }
 }
 return (T) result;
 } (dagger.internal)
  49. DoubleCheck Memoizes value using Double-Check idiom. public T get() {


    Object result = instance;
 if (result == UNINITIALIZED) {
 synchronized (this) {
 result = instance;
 if (result == UNINITIALIZED) {
 result = provider.get();
 
 Object currentInstance = instance; // other code
 instance = result;
 
 provider = null;
 }
 }
 }
 return (T) result;
 } (dagger.internal)
  50. Take Aways • DONT “Scope All the Things!” • Scoping

    has overheads. • By-default no Scope. • Scope only when needed • Like for Heavy Mutable Objects
  51. @ragdroid @droidconDE @REUSABLE

  52. @Reusable • Limit the instantiation. • Use when Exact same

    instance not needed. • Not tied to any component or subcomponent. • Can Have multiple sub-components caching different instances. • Use for heavy immutable dependencies.
  53. ReusableComponent 
 @Component(modules = ReusableModule.class) public interface ReusableComponent { SomeObject

    someObject(); }
  54. ReusableComponent 
 @Component(modules = ReusableModule.class) public interface ReusableComponent { SomeObject

    someObject(); }
  55. SomeObject @Reusable public class SomeObject { @Inject public SomeObject() {

    } }
  56. DaggerReusableComponent @Generated public final class DaggerReusableComponent implements ReusableComponent { /**

    other code **/ Provider<SomeObject> someObjectProvider; private void initialize(final Builder builder) { this.someObjectProvider = SingleCheck.provider(SomeObject_Factory.create()); } } (Generated)
  57. DaggerReusableComponent @Generated public final class DaggerReusableComponent implements ReusableComponent { /**

    other code **/ Provider<SomeObject> someObjectProvider; private void initialize(final Builder builder) { this.someObjectProvider = SingleCheck.provider(SomeObject_Factory.create()); } } (Generated)
  58. DaggerReusableComponent @Generated public final class DaggerReusableComponent implements ReusableComponent { /**

    other code **/ Provider<SomeObject> someObjectProvider; private void initialize(final Builder builder) { this.someObjectProvider = SingleCheck.provider(SomeObject_Factory.create()); } } (Generated)
  59. SingleCheck Memoizes value using simple lazy initialization and caching (dagger.internal)

  60. Memoizes value using simple lazy initialization and caching public T

    get() {
 
 Provider<T> providerReference = provider;
 if (instance == UNINITIALIZED) {
 instance = providerReference.get();
 provider = null;
 }
 return (T) instance;
 } (dagger.internal) SingleCheck
  61. Memoizes value using simple lazy initialization public T get() {


    
 Provider<T> providerReference = provider;
 if (instance == UNINITIALIZED) {
 instance = providerReference.get();
 provider = null;
 }
 return (T) instance;
 } (dagger.internal) SingleCheck
  62. @Singleton vs @Reusable • Heavy mutable object : @Singleton •

    Heavy immutable object : @Reusable •
  63. @ragdroid @droidconDE GOD APP MODULE

  64. @ragdroid @droidconDE App Module AppComponent @Module public class AppModule {

    private final Application application; @Provides @Si AppModule @Singleton @Component(modules = AppModule.class) @Singleton public interface AppComponent { Application application(); }
  65. @ragdroid @droidconDE Big App Module AppComponent @Module public class AppModule

    { private final Application application; @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton AppModule @Singleton @Component(modules = AppModule.class) @Singleton public interface AppComponent { Application application(); }
  66. @ragdroid @droidconDE AppComponent @Module public class AppModule { private final

    Application application; @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } } AppModule @Singleton Big App Module @Component(modules = AppModule.class) @Singleton public interface AppComponent { Application application(); }
  67. @ragdroid @droidconDE AppComponent @Module public class AppModule { private final

    Application application; @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } } AppModule @Singleton God Module God App Module @Component(modules = AppModule.class) @Singleton public interface AppComponent { Application application(); }
  68. @ragdroid @droidconDE God App Module How To Improve?

  69. @ragdroid @droidconDE God App Module Splitting App Module

  70. @ragdroid @droidconDE AppComponent @Module public class AppModule { private final

    Application application; @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } } @Singleton @Component(modules = AppModule.class) @Singleton public interface AppComponent { Application application(); } Splitting App Module ApiModule AppModule
  71. @ragdroid @droidconDE Splitting App Module @Module public class AppModule {

    private final Application application; @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } } AppModule ApiModule AppComponent @Singleton @Component(modules = AppModule.class) @Singleton public interface AppComponent { Application application(); }
  72. @ragdroid @droidconDE Splitting App Module AppComponent @Module public class AppModule

    { private final Application application; @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } } AppModule @Singleton @Component(modules = AppModule.class) @Singleton public interface AppComponent { Application application(); } ApiModule @Component( modules = AppModule.class, ApiModule.class)
  73. @ragdroid @droidconDE Splitting App Module @Module public class AppModule {

    private final Application application; @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } } AppModule ApiModule @Component( modules = AppModule.class, ApiModule.class) OR AppComponent
  74. @ragdroid @droidconDE Splitting App Module @Module public class AppModule {

    private final Application application; @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } @Provides @Singleton Application applicationProvider() { return application; } } AppModule ApiModule @Component( modules = AppModule.class, ApiModule.class) @Module( includes = ApiModule.class) AppModule OR AppComponent
  75. @ragdroid @droidconDE Splitting App Module

  76. @ragdroid @droidconDE How to Improve? • Better Scope Management •

    More modularity • Custom Scopes : • @UserScope • @ActivityScope • @FragmentScope
  77. @ragdroid @droidconDE Custom Scopes

  78. @ragdroid @droidconDE Custom Scopes Multiple Components

  79. Multiple Components 1. Dependent Components 2. Sub-Components

  80. COMPONENT DEPENDENCIES

  81. @ragdroid @droidconDE POKEMON APP

  82. AppComponent (@Singleton) UserComponent (@UserScope) UserComponent @UserScope Login Component @ActivityScope Home

    Component Items Component Login Component Home Component Items Component Fragments Fragments Application
  83. AppComponent (@Singleton) UserComponent (@UserScope) UserComponent @UserScope Login Component @ActivityScope Home

    Component Items Component Login Component Home Component Items Component Fragments Fragments Launch Application
  84. AppComponent (@Singleton) UserComponent (@UserScope) UserComponent @UserScope Login Component @ActivityScope Home

    Component Items Component Login Component Home Component Items Component Fragments Fragments Launch pikachu Login Application
  85. AppComponent (@Singleton) UserComponent (@UserScope) UserComponent @UserScope Login Component @ActivityScope Home

    Component Items Component Login Component Home Component Items Component Fragments Fragments Launch pikachu Login Inventory Application
  86. AppComponent (@Singleton) UserComponent (@UserScope) UserComponent @UserScope Login Component @ActivityScope Home

    Component Items Component Login Component Home Component Items Component Fragments Fragments Launch pikachu Login Log-Out Inventory Application
  87. AppComponent (@Singleton) UserComponent (@UserScope) UserComponent @UserScope Login Component @ActivityScope Home

    Component Items Component Login Component Home Component Items Component Fragments Fragments Launch pikachu Login Log-Out jigglypuff Inventory Application
  88. AppComponent (@Singleton) UserComponent (@UserScope) UserComponent @UserScope Login Component @ActivityScope Home

    Component Items Component Login Component Home Component Items Component Fragments Fragments Launch pikachu Login Log-Out jigglypuff Inventory Inventory Application
  89. Pokemon App

  90. @ragdroid @droidconDE SUB COMPONENT VS DEPENDENT COMPONENT

  91. <<interface>> AppComponent schedulerProvider @Singleton

  92. AppComponentImpl • schedulerProvider() : @Singleton • userManager : @Singleton LoginComponentImpl

    <<interface>> AppComponent schedulerProvider Sub Component @Singleton @ActivityScope
  93. UserComponentImpl • schedulerProvider • pokemon AppComponentImpl • schedulerProvider() : @Singleton

    • userManager : @Singleton LoginComponentImpl <<interface>> AppComponent schedulerProvider HomeComponentImpl ItemsComponentImpl Dependent Component Sub Component @Singleton @ActivityScope @UserScope @ActivityScope @ActivityScope
  94. UserComponentImpl • schedulerProvider • pokemon AppComponentImpl • schedulerProvider() : @Singleton

    • userManager : @Singleton LoginComponentImpl <<interface>> AppComponent schedulerProvider HomeComponentImpl ItemsComponentImpl Dependent Component Sub Component @Singleton @ActivityScope @UserScope @ActivityScope @ActivityScope
  95. @ragdroid @droidconDE APP COMPONENT

  96. @Singleton @Component(modules = arrayOf(AppModule::class, ApiModule::class)) interface AppComponent { fun loginBuilder():

    LoginComponent.Builder fun schedulerProvider(): BaseSchedulerProvider } AppComponent
  97. @Singleton @Component(modules = arrayOf(AppModule::class, ApiModule::class)) interface AppComponent { fun loginBuilder():

    LoginComponent.Builder fun schedulerProvider(): BaseSchedulerProvider } AppComponent
  98. @Singleton @Component(modules = arrayOf(AppModule::class, ApiModule::class)) interface AppComponent { fun loginBuilder():

    LoginComponent.Builder fun schedulerProvider(): BaseSchedulerProvider } AppComponent
  99. @ragdroid @droidconDE DAHAKA APPLICATION

  100. class DahakaApplication : Application() { override fun onCreate() { super.onCreate()

    appComponent = DaggerAppComponent .builder() .application(this) .build() } } DahakaApplication
  101. class DahakaApplication : Application() { override fun onCreate() { super.onCreate()

    appComponent = DaggerAppComponent .builder() .application(this) .build() } } DahakaApplication
  102. DEPENDENT COMPONENTS

  103. @ragdroid @droidconDE USER COMPONENT

  104. @Component(dependencies = arrayOf(AppComponent::class), modules = arrayOf(UserModule::class)) @UserScope interface UserComponent {

    @Component.Builder interface Builder { @BindsInstance fun pokeMon(pokemon: Pokemon): Builder … } } UserComponent
  105. @Component(dependencies = arrayOf(AppComponent::class), modules = arrayOf(UserModule::class)) @UserScope interface UserComponent {

    @Component.Builder interface Builder { @BindsInstance fun pokeMon(pokemon: Pokemon): Builder … } } UserComponent
  106. @Component(dependencies = arrayOf(AppComponent::class), modules = arrayOf(UserModule::class)) @UserScope interface UserComponent {

    @Component.Builder interface Builder { @BindsInstance fun pokeMon(pokemon: Pokemon): Builder … } } UserComponent
  107. Binding Pokemon • Two ways of Providing / Binding Pokemon

    to graph 1. UserModule Constructor 2. @Component.Builder with @BindsInstance
  108. 
 @Module
 public abstract class UserModule {
 
 private final

    Pokemon pokemon;
 
 public UserModule(Pokemon pokemon) {
 this.pokemon = pokemon;
 }
 
 @Provides
 @UserScope
 public Pokemon providePokemon() {
 return pokemon;
 }
 
 }
 UserModule Constructor
  109. 
 @Module
 public abstract class UserModule {
 
 private final

    Pokemon pokemon;
 
 public UserModule(Pokemon pokemon) {
 this.pokemon = pokemon;
 }
 
 @Provides
 @UserScope
 public Pokemon providePokemon() {
 return pokemon;
 }
 
 }
 UserModule Constructor
  110. 
 @Module
 public abstract class UserModule {
 
 private final

    Pokemon pokemon;
 
 public UserModule(Pokemon pokemon) {
 this.pokemon = pokemon;
 }
 
 @Provides
 @UserScope
 public Pokemon providePokemon() {
 return pokemon;
 }
 
 }
 UserModule Constructor
  111. @Component(dependencies = arrayOf(AppComponent::class), modules = arrayOf(UserModule::class)) @UserScope interface UserComponent {

    @Component.Builder interface Builder { @BindsInstance fun pokeMon(pokemon: Pokemon): Builder … } } User Component @Component.Builder
  112. @Component(dependencies = arrayOf(AppComponent::class), modules = arrayOf(UserModule::class)) @UserScope interface UserComponent {

    @Component.Builder interface Builder { @BindsInstance fun pokeMon(pokemon: Pokemon): Builder … } } UserComponent @BindsInstance
  113. @ragdroid @droidconDE USER MANAGER

  114. @Singleton class UserManager @Inject constructor(private val service: PokemonService) { var

    userComponent: UserComponent? = null private set public fun createUserSession(pokemon: Pokemon) { userComponent = DaggerUserComponent.builder() .appComponent(DahakaApplication.app.appComponent) .pokeMon(pokemon) .build() } … } UserManager
  115. @Singleton class UserManager @Inject constructor(private val service: PokemonService) { var

    userComponent: UserComponent? = null private set public fun createUserSession(pokemon: Pokemon) { userComponent = DaggerUserComponent.builder() .appComponent(DahakaApplication.app.appComponent) .pokeMon(pokemon) .build() } … } UserManager
  116. @Singleton class UserManager @Inject constructor(private val service: PokemonService) { var

    userComponent: UserComponent? = null private set public fun createUserSession(pokemon: Pokemon) { userComponent = DaggerUserComponent.builder() .appComponent(DahakaApplication.app.appComponent) .pokeMon(pokemon) .build() } … } UserManager
  117. @ragdroid @droidconDE DAGGER USER COMPONENT (Generated)

  118. public final class DaggerUserComponent implements UserComponent { private Provider<BaseSchedulerProvider> schedulerProvider;

    private void initialize(final Builder builder) { this.schedulerProvider = new AppComponent_schedulerProvider(builder.appComponent); … } private static class AppComponent_schedulerProvider implements Provider<BaseSchedulerProvider> { private final AppComponent appComponent; @Override public BaseSchedulerProvider get() { return appComponent.schedulerProvider(); } … } } DaggerUserComponent (Generated)
  119. public final class DaggerUserComponent implements UserComponent { private Provider<BaseSchedulerProvider> schedulerProvider;

    private void initialize(final Builder builder) { this.schedulerProvider = new AppComponent_schedulerProvider(builder.appComponent); … } private static class AppComponent_schedulerProvider implements Provider<BaseSchedulerProvider> { private final AppComponent appComponent; @Override public BaseSchedulerProvider get() { return appComponent.schedulerProvider(); } … } } DaggerUserComponent (Generated)
  120. public final class DaggerUserComponent implements UserComponent { private Provider<BaseSchedulerProvider> schedulerProvider;

    private void initialize(final Builder builder) { this.schedulerProvider = new AppComponent_schedulerProvider(builder.appComponent); … } private static class AppComponent_schedulerProvider implements Provider<BaseSchedulerProvider> { private final AppComponent appComponent; @Override public BaseSchedulerProvider get() { return appComponent.schedulerProvider(); } … } } DaggerUserComponent (Generated)
  121. public final class DaggerUserComponent implements UserComponent { private Provider<BaseSchedulerProvider> schedulerProvider;

    private void initialize(final Builder builder) { this.schedulerProvider = new AppComponent_schedulerProvider(builder.appComponent); … } private static class AppComponent_schedulerProvider implements Provider<BaseSchedulerProvider> { private final AppComponent appComponent; @Override public BaseSchedulerProvider get() { return appComponent.schedulerProvider(); } … } } DaggerUserComponent (Generated)
  122. public final class DaggerUserComponent implements UserComponent { private Provider<BaseSchedulerProvider> schedulerProvider;

    private void initialize(final Builder builder) { this.schedulerProvider = new AppComponent_schedulerProvider(builder.appComponent); … } private static class AppComponent_schedulerProvider implements Provider<BaseSchedulerProvider> { private final AppComponent appComponent; @Override public BaseSchedulerProvider get() { return appComponent.schedulerProvider(); } … } } DaggerUserComponent (Generated)
  123. public final class DaggerUserComponent implements UserComponent { private Provider<BaseSchedulerProvider> schedulerProvider;

    private void initialize(final Builder builder) { this.schedulerProvider = new AppComponent_schedulerProvider(builder.appComponent); … } private static class AppComponent_schedulerProvider implements Provider<BaseSchedulerProvider> { private final AppComponent appComponent; @Override public BaseSchedulerProvider get() { return appComponent.schedulerProvider(); } … } } DaggerUserComponent (Generated)
  124. SUB COMPONENTS

  125. @ragdroid @droidconDE LOGIN SUBCOMPONENT

  126. @ActivityScope @Subcomponent(modules = arrayOf(LoginModule::class)) interface LoginComponent { @Subcomponent.Builder interface Builder

    { @BindsInstance fun loginActivity(loginActivity: LoginActivity): Builder } } LoginComponent
  127. @ActivityScope @Subcomponent(modules = arrayOf(LoginModule::class)) interface LoginComponent { @Subcomponent.Builder interface Builder

    { @BindsInstance fun loginActivity(loginActivity: LoginActivity): Builder } } LoginComponent
  128. @ActivityScope @Subcomponent(modules = arrayOf(LoginModule::class)) interface LoginComponent { @Subcomponent.Builder interface Builder

    { @BindsInstance fun loginActivity(loginActivity: LoginActivity): Builder } } LoginComponent
  129. @ActivityScope @Subcomponent(modules = arrayOf(LoginModule::class)) interface LoginComponent { @Subcomponent.Builder interface Builder

    { @BindsInstance fun loginActivity(loginActivity: LoginActivity): Builder } } LoginComponent
  130. @ActivityScope @Subcomponent(modules = arrayOf(LoginModule::class)) interface LoginComponent { @Subcomponent.Builder interface Builder

    { @BindsInstance fun loginActivity(loginActivity: LoginActivity): Builder } } LoginComponent
  131. @ragdroid @droidconDE LOGIN ACTIVITY

  132. class LoginActivity { private lateinit var loginComponent: LoginComponent override fun

    initDagger(appComponent: AppComponent) { loginComponent = appComponent .loginBuilder() .loginActivity(this) .build() } … } LoginActivity
  133. class LoginActivity { private lateinit var loginComponent: LoginComponent override fun

    initDagger(appComponent: AppComponent) { loginComponent = appComponent .loginBuilder() .loginActivity(this) .build() } … } LoginActivity
  134. @ragdroid @droidconDE DAGGER APP COMPONENT (Generated)

  135. public final class DaggerAppComponent implements AppComponent { this.loginBuilderProvider = new

    Factory<LoginComponent.Builder>() { @Override public LoginComponent.Builder get() { return new LoginComponentBuilder(); } }; } private final class LoginComponentBuilder implements LoginComponent.Builder { … } private final class LoginComponentImpl implements LoginComponent { private LoginComponentImpl(LoginComponentBuilder builder) { assert builder != null; initialize(builder); } … } } DaggerAppComponent (Generated)
  136. public final class DaggerAppComponent implements AppComponent { this.loginBuilderProvider = new

    Factory<LoginComponent.Builder>() { @Override public LoginComponent.Builder get() { return new LoginComponentBuilder(); } }; } private final class LoginComponentBuilder implements LoginComponent.Builder { … } private final class LoginComponentImpl implements LoginComponent { private LoginComponentImpl(LoginComponentBuilder builder) { assert builder != null; initialize(builder); } … } } DaggerAppComponent (Generated)
  137. public final class DaggerAppComponent implements AppComponent { this.loginBuilderProvider = new

    Factory<LoginComponent.Builder>() { @Override public LoginComponent.Builder get() { return new LoginComponentBuilder(); } }; } private final class LoginComponentBuilder implements LoginComponent.Builder { … } private final class LoginComponentImpl implements LoginComponent { private LoginComponentImpl(LoginComponentBuilder builder) { assert builder != null; initialize(builder); } … } } DaggerAppComponent (Generated)
  138. public final class DaggerAppComponent implements AppComponent { this.loginBuilderProvider = new

    Factory<LoginComponent.Builder>() { @Override public LoginComponent.Builder get() { return new LoginComponentBuilder(); } }; } private final class LoginComponentBuilder implements LoginComponent.Builder { … } private final class LoginComponentImpl implements LoginComponent { private LoginComponentImpl(LoginComponentBuilder builder) { assert builder != null; initialize(builder); } … } } DaggerAppComponent (Generated)
  139. public final class DaggerAppComponent implements AppComponent { this.loginBuilderProvider = new

    Factory<LoginComponent.Builder>() { @Override public LoginComponent.Builder get() { return new LoginComponentBuilder(); } }; } private final class LoginComponentBuilder implements LoginComponent.Builder { … } private final class LoginComponentImpl implements LoginComponent { private LoginComponentImpl(LoginComponentBuilder builder) { assert builder != null; initialize(builder); } … } } DaggerAppComponent (Generated)
  140. public final class DaggerAppComponent implements AppComponent { this.loginBuilderProvider = new

    Factory<LoginComponent.Builder>() { @Override public LoginComponent.Builder get() { return new LoginComponentBuilder(); } }; } private final class LoginComponentBuilder implements LoginComponent.Builder { … } private final class LoginComponentImpl implements LoginComponent { private LoginComponentImpl(LoginComponentBuilder builder) { assert builder != null; initialize(builder); } … } } DaggerAppComponent (Generated)
  141. public final class DaggerAppComponent implements AppComponent { this.loginBuilderProvider = new

    Factory<LoginComponent.Builder>() { @Override public LoginComponent.Builder get() { return new LoginComponentBuilder(); } }; } private final class LoginComponentBuilder implements LoginComponent.Builder { … } private final class LoginComponentImpl implements LoginComponent { private LoginComponentImpl(LoginComponentBuilder builder) { assert builder != null; initialize(builder); } … } } DaggerAppComponent (Generated)
  142. @ragdroid @droidconDE SUB COMPONENT VS DEPENDENT COMPONENT

  143. <<interface>> AppComponent fun schedulerProvider() @Singleton

  144. DaggerAppComponent • schedulerProvider() : @Singleton • userManager : @Singleton LoginComponentImpl

    <<interface>> AppComponent fun schedulerProvider() @Singleton @ActivityScope
  145. DaggerAppComponent • schedulerProvider() : @Singleton • userManager : @Singleton LoginComponentImpl

    <<interface>> AppComponent fun schedulerProvider() Sub Component LoginComponent accesses any dependencies of DaggerAppComponent directly as inner class can access outer class members. @Singleton @ActivityScope
  146. DaggerUserComponent • schedulerProvider • pokemon DaggerAppComponent • schedulerProvider() : @Singleton

    • userManager : @Singleton LoginComponentImpl <<interface>> AppComponent fun schedulerProvider() HomeComponentImpl ItemsComponentImpl Dependent Component UserComponent accesses any dependencies of DaggerAppComponent via an interface of AppComponent. @Singleton @ActivityScope @UserScope @ActivityScope @ActivityScope Sub Component LoginComponent accesses any dependencies of DaggerAppComponent directly as inner class can access outer class members.
  147. DaggerUserComponent • schedulerProvider • pokemon DaggerAppComponent • schedulerProvider() : @Singleton

    • userManager : @Singleton LoginComponentImpl <<interface>> AppComponent fun schedulerProvider() HomeComponentImpl ItemsComponentImpl @Singleton @ActivityScope @UserScope @ActivityScope @ActivityScope Sub Component LoginComponent accesses any dependencies of DaggerAppComponent directly as inner class can access outer class members. Dependent Component UserComponent accesses any dependencies of DaggerAppComponent via an interface of AppComponent.
  148. @ragdroid @droidconDE Custom Scope Advantages • Dependency Lifecycle Management •

    Modularized code
  149. @ragdroid @droidconDE Some Limitations • Repetitive Injection code • Class

    knows about it’s Injector
  150. @ragdroid @droidconDE Some Limitations Dagger 2 Android

  151. INTERMEDIATE CONCEPTS “DEFEAT THE DAHAKA”

  152. @ragdroid @droidconDE @BINDS

  153. @Module public class AppModule { @Provides BaseSchedulerProvider providerSchedulerProvider(SchedulerProvider provider) {

    return provider; } } @Binds
  154. @Module public class AppModule { @Provides BaseSchedulerProvider providerSchedulerProvider(SchedulerProvider provider) {

    return provider; } } @Binds @Module public abstract class AppModule { @Binds abstract BaseSchedulerProvider providerSchedulerProvider(SchedulerProvider provider); }
  155. @ragdroid @droidconDE MULTIBINDING

  156. MultiBinding @IntoSet @Provides String - “Hello” @Provides String - “Hi”

    @Provides String - “How are you?”
  157. @Provides String - “Hello” @Provides String - “Hi” @Provides String

    - “How are you?” @IntoSet @IntoSet @IntoSet MultiBinding @IntoSet
  158. @Provides Set<String> {“Hello”, “Hi”, “How are you?”} MultiBinding @IntoSet

  159. MultiBinding @IntoMap <<interface>> Contract.Presenter MapPresenter JustPresenter TakePresenter

  160. MultiBinding @IntoMap @Provides MapPresenter mapPresenter @Provides JustPresenter justPresenter @Provides TakePresenter

    takePresenter
  161. MultiBinding @IntoMap @Provides MapPresenter mapPresenter @Provides JustPresenter justPresenter @Provides TakePresenter

    takePresenter @IntoMap @IntoMap @IntoMap
  162. MultiBinding @IntoMap @Provides MapPresenter mapPresenter @Provides JustPresenter justPresenter @Provides TakePresenter

    takePresenter @IntoMap @IntoMap @IntoMap @ClassKey(MapPresenter.java) @ClassKey(JustPresenter.java) @ClassKey(TakePresenter.java)
  163. MultiBinding @IntoMap @Provides Map<Class, Contract.Presenter> { mapPresenter, justPresenter, takePresenter }

  164. DAGGER 2 ANDROID “BEFRIEND THE BEAST”

  165. @ragdroid @droidconDE DAHAKA APPLICATION

  166. class DahakaApplication : Application(), HasActivityInjector { @Inject internal lateinit var

    activityInjector: DispatchingAndroidInjector<Activity> … override fun activityInjector(): AndroidInjector<Activity> { return activityInjector } … } DahakaApplication
  167. class DahakaApplication : Application(), HasActivityInjector { @Inject internal lateinit var

    activityInjector: DispatchingAndroidInjector<Activity> … override fun activityInjector(): AndroidInjector<Activity> { return activityInjector } … } DahakaApplication
  168. class DahakaApplication : Application(), HasActivityInjector { @Inject internal lateinit var

    activityInjector: DispatchingAndroidInjector<Activity> … override fun activityInjector(): AndroidInjector<Activity> { return activityInjector } … } DahakaApplication
  169. class DahakaApplication : Application(), HasActivityInjector { @Inject internal lateinit var

    activityInjector: DispatchingAndroidInjector<Activity> … override fun activityInjector(): AndroidInjector<Activity> { return activityInjector } … } DahakaApplication
  170. public interface HasActivityInjector { AndroidInjector<Activity> activityInjector(); } HasActivityInjector

  171. HasActivityInjector • A simple interface. • Implementing class “Has” ActivityInjector.

    • ActivityInjector = AndroidInjector<Activity>. public interface HasActivityInjector { AndroidInjector<Activity> activityInjector(); }
  172. HasActivityInjector <<interface>> HasActivityInjector fun activityInjector() : AndroidInjector<Activity>

  173. HasActivityInjector <<interface>> HasActivityInjector fun activityInjector() : AndroidInjector<Activity> DahakaApplication • activityInjector

    : DispatchingAndroidInjector<Activity>
  174. HasActivityInjector <<interface>> HasActivityInjector fun activityInjector() : AndroidInjector<Activity> DahakaApplication • activityInjector

    : DispatchingAndroidInjector<Activity> <<interface>> AndroidInjector<Activity> fun inject(Activity instance)
  175. HasActivityInjector <<interface>> HasActivityInjector fun activityInjector() : AndroidInjector<Activity> DahakaApplication • activityInjector

    : DispatchingAndroidInjector<Activity> DispatchingAndroidInjector<Activity> • inject(Activity activity) • injectorFactories : Map <<interface>> AndroidInjector<Activity> fun inject(Activity instance)
  176. DispatchingAndroidInjector • Injects members for Android types : Activity, Fragment,

    etc • Has a Map<Class, Provider<Factory>> injectorFactories.
  177. DispatchingAndroidInjector Provider<LoginActivitySubcomponent.Builder> LoginActivity.class Class<Activity> Provider<Factory<Activity>> DispatchingAndroidInject<Activity> • gets the Subcomponent.Builder

    from Map. • creates an instance using Builder. • calls component.inject(instance) to perform injections. • Injects members for Android types : Activity, Fragment, etc • Has a Map<Class, Provider<Factory>> injectorFactories.
  178. Provider<HomeActivitySubcomponent.Builder> HomeActivity.class ItemsActivity.class Provider<ItemsActivitySubcomponent.Builder> Provider<ProfileFragmentSubcomponent.Builder> ProfileFragment.class MovesFragment.class Provider<MovesFragmentSubcomponent.Builder> Class<Fragment> Provider<Factory<Fragment>>

    Provider<StatsFragmentSubcomponent.Builder> StatsFragment.class DispatchingAndroidInjector Provider<LoginActivitySubcomponent.Builder> LoginActivity.class Class<Activity> Provider<Factory<Activity>> DispatchingAndroidInject<Activity> DispatchingAndroidInject<Fragment>
  179. @ragdroid @droidconDE APP COMPONENT

  180. @Singleton @Component(modules = arrayOf(AppModule::class, ApiModule::class, AppBindingModule::class, AndroidSupportInjectionModule::class)) interface AppComponent :

    AndroidInjector<DaggerApplication> { … } AppComponent
  181. AppBindingModule @Singleton @Component(modules = arrayOf(AppModule::class, ApiModule::class, AppBindingModule::class, AndroidSupportInjectionModule::class)) interface AppComponent

    : AndroidInjector<DaggerApplication> { … } AppComponent
  182. @Module abstract class AppBindingModule { @ContributesAndroidInjector(modules = arrayOf(LoginModule::class)) @ActivityScope internal

    abstract fun loginActivity(): LoginActivity } AppBindingModule
  183. @ContributesAndroidInjector @Module abstract class AppBindingModule { @ContributesAndroidInjector(modules = arrayOf(LoginModule::class)) @ActivityScope

    internal abstract fun loginActivity(): LoginActivity } AppBindingModule
  184. @Module abstract class AppBindingModule { @ContributesAndroidInjector(modules = arrayOf(LoginModule::class)) @ActivityScope internal

    abstract fun loginActivity(): LoginActivity } AppBindingModule • If your Module is stateless. • If your Subcomponent.Builder is simple and doesn’t need to bind anything extra. • @ContributesAndroidInjector will generate the SubComponent for you. • No need to create LoginActivitySubcomponent class in the above case. @ContributesAndroidInjector AppBindingModule
  185. @Module abstract class AppBindingModule { @ContributesAndroidInjector(modules = arrayOf(LoginModule::class)) @ActivityScope internal

    abstract fun loginActivity(): LoginActivity } AppBindingModule @Module abstract class LoginModule { @Binds abstract fun provideLoginPresenter(loginPresenter: LoginPresenter): LoginContract.Presenter } LoginModule
  186. @Module(subcomponents = LoginActivitySubcomponent.class) public abstract class AppBindingModule_LoginActivity { @Binds @IntoMap

    @ActivityKey(LoginActivity.class) abstract AndroidInjector.Factory<? extends Activity> bindAndroidInjectorFactory( LoginActivitySubcomponent.Builder builder); @Subcomponent(modules = LoginModule.class) @ActivityScope public interface LoginActivitySubcomponent extends AndroidInjector<LoginActivity> { @Subcomponent.Builder abstract class Builder extends AndroidInjector.Builder<LoginActivity> {} } } LoginBindingModule(Generated)
  187. @Module(subcomponents = LoginActivitySubcomponent.class) public abstract class AppBindingModule_LoginActivity { @Binds @IntoMap

    @ActivityKey(LoginActivity.class) abstract AndroidInjector.Factory<? extends Activity> bindAndroidInjectorFactory( LoginActivitySubcomponent.Builder builder); @Subcomponent(modules = LoginModule.class) @ActivityScope public interface LoginActivitySubcomponent extends AndroidInjector<LoginActivity> { @Subcomponent.Builder abstract class Builder extends AndroidInjector.Builder<LoginActivity> {} } } LoginBindingModule(Generated)
  188. @Module(subcomponents = LoginActivitySubcomponent.class) public abstract class AppBindingModule_LoginActivity { @Binds @IntoMap

    @ActivityKey(LoginActivity.class) abstract AndroidInjector.Factory<? extends Activity> bindAndroidInjectorFactory( LoginActivitySubcomponent.Builder builder); @Subcomponent(modules = LoginModule.class) @ActivityScope public interface LoginActivitySubcomponent extends AndroidInjector<LoginActivity> { @Subcomponent.Builder abstract class Builder extends AndroidInjector.Builder<LoginActivity> {} } } LoginBindingModule(Generated)
  189. @Module(subcomponents = LoginActivitySubcomponent.class) public abstract class AppBindingModule_LoginActivity { @Binds @IntoMap

    @ActivityKey(LoginActivity.class) abstract AndroidInjector.Factory<? extends Activity> bindAndroidInjectorFactory( LoginActivitySubcomponent.Builder builder); @Subcomponent(modules = LoginModule.class) @ActivityScope public interface LoginActivitySubcomponent extends AndroidInjector<LoginActivity> { @Subcomponent.Builder abstract class Builder extends AndroidInjector.Builder<LoginActivity> {} } } LoginBindingModule(Generated)
  190. @Module(subcomponents = LoginActivitySubcomponent.class) public abstract class AppBindingModule_LoginActivity { @Binds @IntoMap

    @ActivityKey(LoginActivity.class) abstract AndroidInjector.Factory<? extends Activity> bindAndroidInjectorFactory( LoginActivitySubcomponent.Builder builder); @Subcomponent(modules = LoginModule.class) @ActivityScope public interface LoginActivitySubcomponent extends AndroidInjector<LoginActivity> { @Subcomponent.Builder abstract class Builder extends AndroidInjector.Builder<LoginActivity> {} } } LoginBindingModule(Generated)
  191. AndroidSupportInjectionModule AppBindingModule @Singleton @Component(modules = arrayOf(AppModule::class, ApiModule::class, AppBindingModule::class, AndroidSupportInjectionModule::class)) interface

    AppComponent : AndroidInjector<DaggerApplication> { … } AppComponent
  192. @Beta @Module(includes = AndroidInjectionModule.class) public abstract class AndroidSupportInjectionModule { @Multibinds

    abstract Map<Class<? extends Fragment>, AndroidInjector.Factory<? extends Fragment>> supportFragmentInjectorFactories(); private AndroidSupportInjectionModule() {} } @Beta @Module public abstract class AndroidInjectionModule { @Multibinds abstract Map<Class<? extends Activity>, AndroidInjector.Factory<? extends Activity>> activityInjectorFactories(); @Multibinds abstract Map<Class<? extends Fragment>, AndroidInjector.Factory<? extends Fragment>> fragmentInjectorFactories(); … } AndroidSupportInjectionModule (dagger.android)
  193. @Beta @Module(includes = AndroidInjectionModule.class) public abstract class AndroidSupportInjectionModule { @Multibinds

    abstract Map<Class<? extends Fragment>, AndroidInjector.Factory<? extends Fragment>> supportFragmentInjectorFactories(); private AndroidSupportInjectionModule() {} } @Beta @Module public abstract class AndroidInjectionModule { @Multibinds abstract Map<Class<? extends Activity>, AndroidInjector.Factory<? extends Activity>> activityInjectorFactories(); @Multibinds abstract Map<Class<? extends Fragment>, AndroidInjector.Factory<? extends Fragment>> fragmentInjectorFactories(); … } AndroidSupportInjectionModule (dagger.android)
  194. @Beta @Module(includes = AndroidInjectionModule.class) public abstract class AndroidSupportInjectionModule { @Multibinds

    abstract Map<Class<? extends Fragment>, AndroidInjector.Factory<? extends Fragment>> supportFragmentInjectorFactories(); private AndroidSupportInjectionModule() {} } @Beta @Module public abstract class AndroidInjectionModule { @Multibinds abstract Map<Class<? extends Activity>, AndroidInjector.Factory<? extends Activity>> activityInjectorFactories(); @Multibinds abstract Map<Class<? extends Fragment>, AndroidInjector.Factory<? extends Fragment>> fragmentInjectorFactories(); … } AndroidSupportInjectionModule (dagger.android)
  195. @Beta @Module(includes = AndroidInjectionModule.class) public abstract class AndroidSupportInjectionModule { @Multibinds

    abstract Map<Class<? extends Fragment>, AndroidInjector.Factory<? extends Fragment>> supportFragmentInjectorFactories(); private AndroidSupportInjectionModule() {} } @Beta @Module public abstract class AndroidInjectionModule { @Multibinds abstract Map<Class<? extends Activity>, AndroidInjector.Factory<? extends Activity>> activityInjectorFactories(); @Multibinds abstract Map<Class<? extends Fragment>, AndroidInjector.Factory<? extends Fragment>> fragmentInjectorFactories(); … } AndroidSupportInjectionModule (dagger.android)
  196. @Beta @Module(includes = AndroidInjectionModule.class) public abstract class AndroidSupportInjectionModule { @Multibinds

    abstract Map<Class<? extends Fragment>, AndroidInjector.Factory<? extends Fragment>> supportFragmentInjectorFactories(); private AndroidSupportInjectionModule() {} } @Beta @Module public abstract class AndroidInjectionModule { @Multibinds abstract Map<Class<? extends Activity>, AndroidInjector.Factory<? extends Activity>> activityInjectorFactories(); @Multibinds abstract Map<Class<? extends Fragment>, AndroidInjector.Factory<? extends Fragment>> fragmentInjectorFactories(); … } AndroidSupportInjectionModule (dagger.android)
  197. @ragdroid @droidconDE LOGIN ACTIVITY

  198. public class LoginActivity { @Inject LoginContract.Presenter presenter; @Override protected void

    onCreate(Bundle savedInstanceState) { AndroidInjection.inject(this); } } LoginActivity
  199. AndroidInjection.inject(LoginActivity) LoginActivity public class LoginActivity { @Inject LoginContract.Presenter presenter; @Override

    protected void onCreate(Bundle savedInstanceState) { AndroidInjection.inject(this); } }
  200. AndroidInjection.inject(LoginActivity) AndroidInjection.inje

  201. AndroidInjection.inject(LoginActivity) AndroidInjection.inje AndroidInjection

  202. AndroidInjection.inject(LoginActivity) AndroidInjection.inje AndroidInjection DaggerAppComponent

  203. AndroidInjection.inject(LoginActivity) AndroidInjection.inje AndroidInjection DaggerAppComponent AppBindingModule_LoginActivity DispatchingAndroidInjector

  204. AndroidInjection.inject(LoginActivity) AndroidInjection.inje AndroidInjection DaggerAppComponent AppBindingModule_LoginActivity DispatchingAndroidInjector

  205. AndroidInjection.inject(LoginActivity) AndroidInjection.inje AndroidInjection DaggerAppComponent AppBindingModule_LoginActivity DispatchingAndroidInjector ApiModule_ProvideRetrofitFactory AppModule_ProviderSchedulerProviderFactory ApiModule_ProvidePokemonServiceFactory ApiModule_ProvideRetrofitFactory

    AppModule_ProviderSchedulerProviderFactory ApiModule_ProvidePokemonServiceFactory
  206. @ragdroid @droidconDE BEFRIEND THE BEAST “You can not change your

    fate, No droid can.”
  207. AndroidInjection.inject(LoginActivity)

  208. AndroidInjection.inject(LoginActivity) activity .getApplication() LoginActivity

  209. AndroidInjection.inject(LoginActivity) activity .getApplication() LoginActivity application .activityInjector() DahakaApplication : HasActivityInjector

  210. AndroidInjection.inject(LoginActivity) activity .getApplication() LoginActivity application .activityInjector() DahakaApplication : HasActivityInjector activityInjector

    .inject(activity) DispatchingAndroidInjector : AndroidInjector
  211. AndroidInjection.inject(LoginActivity) activity .getApplication() LoginActivity application .activityInjector() DahakaApplication : HasActivityInjector activityInjector

    .inject(activity) DispatchingAndroidInjector : AndroidInjector
  212. DispatchingAndroidInjector.inject(LoginActivity) injectorFactories .get(LoginActivity.class) DispatchingAndroidInjector : AndroidInjector

  213. DispatchingAndroidInjector : AndroidInjector Factory<LoginActivity> : LoginSubcomponent.Builder injectorFactories .get(LoginActivity.class) DispatchingAndroidInjector.inject(LoginActivity) builder

    .build()
  214. DispatchingAndroidInjector : AndroidInjector Factory<LoginActivity> : LoginSubcomponent.Builder component .inject(activity) LoginSubcomponent injectorFactories

    .get(LoginActivity.class) DispatchingAndroidInjector.inject(LoginActivity) builder .build()
  215. DispatchingAndroidInjector : AndroidInjector builder .build() Factory<LoginActivity> : LoginSubcomponent.Builder component .inject(activity)

    LoginSubcomponent DispatchingAndroidInjector.inject(LoginActivity) injectorFactories .get(LoginActivity.class)
  216. • DaggerApplication • DaggerActivity • DaggerBroadcastReceiver • DaggerContentProvider • DaggerFragment

    • DaggerIntentService • DaggerService Dagger Boilerplate classes
  217. @ragdroid @droidconDE TESTING WITH DAGGER 2 ANDROID

  218. public class LoginActivity { @Inject LoginContract.Presenter presenter; @Override protected void

    onCreate(Bundle savedInstanceState) { AndroidInjection.inject(this); } } LoginActivity
  219. public class LoginActivity { @Inject LoginContract.Presenter presenter; @Override protected void

    onCreate(Bundle savedInstanceState) { AndroidInjection.inject(this); } } LoginActivity
  220. @Module public class TestLoginModule { @Mock LoginPresenter loginPresenter; public TestLoginModule()

    { MockitoAnnotations.initMocks(this); } @Provides @ActivityScope public LoginContract.Presenter provideLoginPresenter() { return loginPresenter; } } TestLoginModule
  221. @Module public class TestLoginModule { @Mock LoginPresenter loginPresenter; public TestLoginModule()

    { MockitoAnnotations.initMocks(this); } @Provides @ActivityScope public LoginContract.Presenter provideLoginPresenter() { return loginPresenter; } } TestLoginModule
  222. @Module public class TestLoginModule { @Mock LoginPresenter loginPresenter; public TestLoginModule()

    { MockitoAnnotations.initMocks(this); } @Provides @ActivityScope public LoginContract.Presenter provideLoginPresenter() { return loginPresenter; } } TestLoginModule
  223. Demo Code • Dahaka Demo : https://github.com/ragdroid/Dahaka • Branches :

    • dagger-android : Pokemon app using dagger-android (With Tests, Fragments) • dagger-android-dependent-comp : dagger-android with Dependent Component • dagger-android-dependent-comp-kotlin : In Kotlin • subcomponent : UserComponent as subcomponent • dependent-component : UserComponent as dependent component • dependent-component-kotlin : In Kotlin
  224. @ragdroid @droidconDE Dagger 2 Android = Dahaka • D •

    A • H • A • K • A Dagger Android HasActivityInjector AndroidInjection Keys AndroidInjector
  225. @ragdroid @droidconDE Dagger 2 Android “You can not change your

    fate, No droid can” Let’s befriend the beast instead.
  226. Acknowledgements • Dagger Recipies : Miroslaw Stanek (@froger_mcs) https://about.me/froger_mcs •

    todo-mvp-dagger : Mike Nakhimovich (@friendlyMikhail ) https://github.com/googlesamples/android-architecture/tree/todo-mvp-dagger • Android Dialogs : Mike Nakhimovich https://www.youtube.com/watch?v=KwRXQ6nT7jQ • Proof Reading : Ritesh Gupta (@_riteshhh) • Migrate to Kotlin : Ravindra Kumar (@ravidsrk)
  227. What Next? • Dagger Documentation : https://google.github.io/dagger// • todo-mvp-dagger :

    Mike Nakhimovich (@friendlyMikhail ) https://github.com/googlesamples/android-architecture/tree/todo-mvp-dagger • Android Dialogs : Mike Nakhimovich https://www.youtube.com/watch?v=KwRXQ6nT7jQ • Dagger Example https://github.com/ragdroid/Dahaka • Testing article https://android.jlelse.eu/testing-your-app-with-dagger-2-c91cdc0860fb • Dagger and the Dahaka Series : https://medium.com/@ragdroid
  228. Other References • Theme : Prince of Persia https://en.wikipedia.org/wiki/Prince_of_Persia •

    Dahaka https://files.gamebanana.com/img/ico/sprays/dahaka.png • Dagger https://in.pinterest.com/pin/397442735844321339/ • Android http://www.pngmart.com/files/4/Android-PNG-Image.png
  229. @ragdroid @droidconDE CUT SCENES

  230. Dagger 2 Android “Defeat the Dahaka" Garima Jain @ragdroid

  231. Dagger 2 Android “Defeat the Dahaka" Garima Jain @ragdroid

  232. FUELED http://fueled.com/garima garima@fueled.com VIELEN DANK THANK YOU

  233. FUELED http://fueled.com/garima garima@fueled.com Q & A DISCUSSION @ragdroid