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

Dagger 2 Android: Defeat the Dahaka

A3958eeb9a7f402b134c0c017d6614ee?s=47 ragdroid
April 13, 2018

Dagger 2 Android: Defeat the Dahaka

A3958eeb9a7f402b134c0c017d6614ee?s=128

ragdroid

April 13, 2018
Tweet

Transcript

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

    @chicagoroboto
  2. @ragdroid #chicagoroboto POP QUIZ • Dagger2? • Dagger Android •

    Prince of Persia
  3. ABOUT THE TALK

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

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

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

    generated code • Developer is chased by the Dahaka (complexity of generated code)
  7. Agenda • Scopes - “Face of the Dahaka” • @Singleton

    Scopes • @Reusable Scopes • Custom Scopes • Component Dependencies - “Unleash the Beast” • Dependent Component • Subcomponent • Dagger Android - “Befriend the Beast”
  8. Who? Assumption : Basic familiarity with Dagger

  9. SCOPES “FACE OF THE DAHAKA”

  10. Scope How long a scoped instance lives (javax.inject)

  11. @Singleton Scope of dependency is throughout the application (javax.inject)

  12. @ragdroid #chicagoroboto @SINGLETON EXAMPLE

  13. AppComponent @Component(modules = [AppModule::class]) @Singleton interface AppComponent { fun application():

    Application }
  14. AppComponent @Component(modules = [AppModule::class]) @Singleton interface AppComponent { fun application():

    Application }
  15. @ragdroid #chicagoroboto CASE 1 DEPENDENCY WITH SCOPE

  16. AppModule @Module class AppModule(val application: Application) { @Provides @Singleton fun

    provideApplication(): Application = application }
  17. AppModule @Module class AppModule(val application: Application) { @Provides @Singleton fun

    provideApplication(): Application = application }
  18. 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)
  19. Provider 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)
  20. Provider • For each @Provides annotation dagger generates a Provider

    * • Dagger’s Factory<T> interface is also a Provider • Dagger has various implementations of Providers: • SingleCheck • DoubleCheck (javax.inject) * Not for unscoped dependencies - Coming up
  21. 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)
  22. 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)
  23. 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)
  24. 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)
  25. DoubleCheck Memoizes value using Double-Check idiom. (dagger.internal)

  26. 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)
  27. 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)
  28. 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)
  29. @ragdroid #chicagoroboto CASE 2 DEPENDENCY W/O SCOPE

  30. AppModule @Module class AppModule(val application: Application) { @Provides //No @Singleton

    annotation fun provideApplication(): Application = application }
  31. AppModule @Module class AppModule(val application: Application) { @Provides //No @Singleton

    annotation fun provideApplication(): Application = application }
  32. DaggerAppComponent @Generated public final class DaggerAppComponent implements AppComponent { private

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

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

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

    appModule; @Override public Application application() { //No Factory Instance Creation return ApplicationFactory.proxyProviderApplication(appModule); } } (Generated) Since dagger 2.12
  36. DaggerAppComponent public final class DaggerAppComponent implements AppComponent { private AppModule

    appModule; @Override public Application application() { //No Factory Instance Creation return ApplicationFactory.proxyProviderApplication(appModule); } } (Generated) Since dagger 2.12
  37. DaggerAppComponent public final class DaggerAppComponent implements AppComponent { private AppModule

    appModule; @Override public Application application() { //No Factory Instance Creation return appModule.provideApplication(); } } (Generated) Since dagger 2.12
  38. Take Aways • DONT “Scope All the Things!” • Scoping

    has overheads. • By-default no Scope. • Scope only when needed • Like for Heavy Objects
  39. @ragdroid #chicagoroboto CASE 3 @REUSABLE

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

    instance not needed. • Can Have multiple sub-components caching different instances.
  41. ReusableComponent 
 @Component(modules = [ReusableModule::class]) interface ReusableComponent { fun someObject():

    SomeObject }
  42. ReusableComponent 
 @Component(modules = [ReusableModule::class]) interface ReusableComponent { fun someObject():

    SomeObject }
  43. SomeObject @Reusable class SomeObject @Inject constructor()

  44. 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)
  45. 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)
  46. 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)
  47. SingleCheck Memoizes value using simple lazy initialization and caching (dagger.internal)

  48. 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
  49. 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
  50. @Singleton vs @Reusable vs No Scope • Heavy mutable object

    with State : @Singleton • Heavy immutable object / stateless : @Reusable • Not Heavy : No Scope •
  51. @ragdroid #chicagoroboto GOD APP MODULE

  52. @ragdroid #chicagoroboto 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(); }
  53. @ragdroid #chicagoroboto 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(); }
  54. @ragdroid #chicagoroboto 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(); }
  55. @ragdroid #chicagoroboto 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(); }
  56. @ragdroid #chicagoroboto God App Module How To Improve?

  57. @ragdroid #chicagoroboto God App Module Splitting App Module

  58. @ragdroid #chicagoroboto 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
  59. @ragdroid #chicagoroboto 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(); }
  60. @ragdroid #chicagoroboto 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)
  61. @ragdroid #chicagoroboto Splitting App Module

  62. @ragdroid #chicagoroboto How to Improve? • Better Scope Management •

    More modularity • Custom Scopes : • @UserScope • @ActivityScope • @FragmentScope
  63. @ragdroid #chicagoroboto Custom Scopes

  64. @ragdroid #chicagoroboto Custom Scopes Multiple Components

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

  66. COMPONENT DEPENDENCIES

  67. @ragdroid #chicagoroboto SUB COMPONENT VS DEPENDENT COMPONENT

  68. 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 Application
  69. AppComponent @Singleton DaggerAppComponent LoginComponent Sub Component @ActivityScope Dependent Component DaggerUserComponent

    • dependency HomeComponent ItemsComponent @UserScope
  70. @ragdroid #chicagoroboto APP COMPONENT

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

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

    LoginComponent.Builder } AppComponent
  73. @ragdroid #chicagoroboto DAHAKA APPLICATION

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

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

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

  77. @ragdroid #chicagoroboto USER COMPONENT

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

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

    } UserComponent
  80. @ragdroid #chicagoroboto USER MANAGER

  81. @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
  82. @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
  83. @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
  84. @ragdroid #chicagoroboto DAGGER USER COMPONENT (Generated)

  85. public final class DaggerUserComponent implements UserComponent { … } DaggerUserComponent

    (Generated)
  86. public final class DaggerUserComponent implements UserComponent { … } DaggerUserComponent

    (Generated)
  87. SUB COMPONENTS

  88. @ragdroid #chicagoroboto LOGIN SUBCOMPONENT

  89. @ActivityScope @Subcomponent(modules = arrayOf(LoginModule::class)) interface LoginComponent { ... } LoginComponent

  90. @ActivityScope @Subcomponent(modules = arrayOf(LoginModule::class)) interface LoginComponent { ... } LoginComponent

  91. @ActivityScope @Subcomponent(modules = arrayOf(LoginModule::class)) interface LoginComponent { ... } LoginComponent

  92. @ragdroid #chicagoroboto DAGGER APP COMPONENT (Generated)

  93. public final class DaggerAppComponent implements AppComponent { private final class

    LoginComponentImpl implements LoginComponent { private LoginComponentImpl(LoginComponentBuilder builder) { assert builder != null; initialize(builder); } … } } DaggerAppComponent(Generated)
  94. public final class DaggerAppComponent implements AppComponent { private final class

    LoginComponentImpl implements LoginComponent { private LoginComponentImpl(LoginComponentBuilder builder) { assert builder != null; initialize(builder); } … } } DaggerAppComponent(Generated)
  95. public final class DaggerAppComponent implements AppComponent { private final class

    LoginComponentImpl implements LoginComponent { private LoginComponentImpl(LoginComponentBuilder builder) { assert builder != null; initialize(builder); } … } } DaggerAppComponent(Generated)
  96. public final class DaggerAppComponent implements AppComponent { private final class

    LoginComponentImpl implements LoginComponent { private LoginComponentImpl(LoginComponentBuilder builder) { assert builder != null; initialize(builder); } … } } DaggerAppComponent(Generated)
  97. @ragdroid #chicagoroboto SUB COMPONENT VS DEPENDENT COMPONENT

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

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

    <<interface>> AppComponent fun schedulerProvider() @Singleton @ActivityScope
  100. 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
  101. 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.
  102. 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.
  103. @ragdroid #chicagoroboto Custom Scope Advantages • Dependency Lifecycle Management •

    Modularized code
  104. @ragdroid #chicagoroboto Some Limitations • Repetitive Injection code • Class

    knows about it’s Injector
  105. @ragdroid #chicagoroboto Some Limitations Dagger 2 Android

  106. DAGGER 2 ANDROID “BEFRIEND THE BEAST”

  107. @ragdroid #chicagoroboto DAHAKA APPLICATION

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

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

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

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

    var activityInjector: DispatchingAndroidInjector<Activity> … override fun activityInjector(): AndroidInjector<Activity> { return activityInjector } … } DahakaApplication
  112. @ragdroid #chicagoroboto APP COMPONENT

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

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

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

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

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

    abstract fun loginActivity(): LoginActivity } AppBindingModule No need to create LoginActivitySubcomponent class in the above case. @ContributesAndroidInjector AppBindingModule
  118. @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
  119. @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)
  120. @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)
  121. @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)
  122. @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)
  123. @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)
  124. @ragdroid #chicagoroboto LOGIN ACTIVITY

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

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

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

  128. AndroidInjection.inject(LoginActivity) AndroidInjection.inje AndroidInjection

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

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

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

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

    AppModule_ProviderSchedulerProviderFactory ApiModule_ProvidePokemonServiceFactory
  133. @ragdroid #chicagoroboto BEFRIEND THE BEAST “You can not change your

    fate, No droid can.”
  134. public interface HasActivityInjector { AndroidInjector<Activity> activityInjector(); } HasActivityInjector

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

    public interface HasActivityInjector { AndroidInjector<Activity> activityInjector(); }
  136. HasActivityInjector <<interface>> HasActivityInjector fun activityInjector() : AndroidInjector<Activity>

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

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

    : DispatchingAndroidInjector<Activity> <<interface>> AndroidInjector<Activity> fun inject(Activity instance)
  139. 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)
  140. DispatchingAndroidInjector Provider<LoginActivitySubcomponent.Builder> LoginActivity.class Class<Activity> Provider<Subcomponent.Builder> DispatchingAndroidInject<Activity> • gets the Subcomponent.Builder

    from injectorFactory. • 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<Subcomponent.Builder>> injectorFactories.
  141. AndroidInjection.inject(LoginActivity)

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

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

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

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

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

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

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

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

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

    • DaggerIntentService • DaggerService Dagger Boilerplate classes
  151. @ragdroid #chicagoroboto Dagger 2 Android = Dahaka • D •

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

    fate, No droid can” Let’s befriend the beast instead.
  153. @ragdroid #chicagoroboto LOGIN ACTIVITY

  154. AndroidInjection.inject(LoginActivity) LoginActivity public class LoginActivity { @Inject LoginContract.Presenter presenter; @Override

    protected void onCreate(Bundle savedInstanceState) { val appComponent = ((application as DahakaApplication) .appComponent) loginComponent = appComponent .loginBuilder() .loginActivity(this) .build() loginComponent.inject(this) } }
  155. LoginActivity public class LoginActivity { @Inject LoginContract.Presenter presenter; @Override protected

    void onCreate(Bundle savedInstanceState) { AndroidInjection.inject(this); } }
  156. 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 • 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
  157. 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)
  158. Demo Code • Dahaka Demo : https://github.com/ragdroid/Dahaka • Branches :

    • dagger-android : Pokemon app using dagger-android (With Tests, Fragments) • dagger-android-dependent-comp-kotlin : dagger-android with Dependent Component • subcomponent : UserComponent as subcomponent • dependent-component-kotlin : UserComponent as dependent component
  159. 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
  160. @ragdroid #chicagoroboto CUT SCENES

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

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

  163. FUELED http://fueled.com/garima garima@fueled.com THANK YOU

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