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

Dagger 2 Android : Defeat the Dahaka DevFestND 2017

ragdroid
October 28, 2017

Dagger 2 Android : Defeat the Dahaka DevFestND 2017

Ppt for DevFest New Delhi, 2017 (Noida Track) @ToTheNew

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

ragdroid

October 28, 2017
Tweet

More Decks by ragdroid

Other Decks in Programming

Transcript

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

    View Slide

  2. Garima Jain
    @ragdroid

    View Slide

  3. Garima Jain
    @ragdroid

    View Slide

  4. Garima Jain
    @ragdroid

    View Slide

  5. Garima Jain
    @ragdroid

    View Slide

  6. Garima Jain
    @ragdroid

    View Slide

  7. Garima Jain
    @ragdroid

    View Slide

  8. @ragdroid
    @droidconDE

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  12. ABOUT THE TALK

    View Slide

  13. Theme: Prince of Persia
    • Prince uses Dagger
    • Dagger can reverse time
    • Dahaka, (guardian of timeline)
    • Dahaka comes to kill the Prince.

    View Slide

  14. Analogy
    • Prince = Us
    • Dagger = Dagger
    • Dahaka (Enemy) = Generated Code, Complexity

    View Slide

  15. Analogy
    • Developer uses Dagger
    • Developer starts backtracking the generated code
    • Developer is chased by the Dahaka (complexity of generated code)

    View Slide

  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”

    View Slide

  17. Who?
    • Assumption : Basic familiarity with Dagger
    • Intermediate

    View Slide

  18. INTRODUCTION
    “CODES OF TIME”

    View Slide

  19. @ragdroid
    @droidconDE
    Droid of Asia

    View Slide

  20. @ragdroid
    @droidconDE
    public UserManager() {

    this.service = new PokemonService(); 

    }
    Droid of Asia

    View Slide

  21. @ragdroid
    @droidconDE
    Dependency Creation Disadvantages
    • Non-Testable
    • Non-Extendable

    View Slide

  22. @ragdroid
    @droidconDE
    Dagger 1

    View Slide

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

    View Slide

  24. @ragdroid
    @droidconDE
    Dagger 1 Disadvantages
    • Reflection
    • Runtime Graph Composition
    • God Module with @Singleton
    • Difficult to use proguard

    View Slide

  25. @ragdroid
    @droidconDE
    Dagger 1 Disadvantages
    Dagger 2

    View Slide

  26. @ragdroid
    @droidconDE
    Dagger 2 Advantages
    • No Reflection
    • Compile-time Graph Composition
    • Traceable code
    • Better Scope management

    View Slide

  27. SCOPES
    “FACE OF THE DAHAKA”

    View Slide

  28. Scope
    • Annotation from java.inject package
    • How long a scoped instance lives

    View Slide

  29. @Singleton
    • Scope of dependency is throughout the application
    • Two ways to re-use dependencies :
    • Annotate Provider methods
    • Annotate the Dependency class itself
    (javax.inject)

    View Slide

  30. @ragdroid
    @droidconDE
    @SINGLETON
    VS
    NO SCOPE
    EXAMPLE

    View Slide

  31. AppComponent
    @Component(modules = AppModule.class)
    @Singleton
    public interface AppComponent {
    SomeDependency someDependency();
    }

    View Slide

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

    View Slide

  33. @ragdroid
    @droidconDE
    CASE 1
    DEPENDENCY W/O SCOPE

    View Slide

  34. AppModule
    @Module
    public class AppModule {
    @Provides //No @Singleton annotation
    SomeDependency applicationProvider() {
    return new SomeDependency();
    }
    }

    View Slide

  35. AppModule
    @Module
    public class AppModule {
    @Provides //No @Singleton annotation
    SomeDependency applicationProvider() {
    return new SomeDependency();
    }
    }

    View Slide

  36. DaggerAppComponent
    @Generated
    public final class DaggerAppComponent implements AppComponent {
    private Provider someDependencyProvider;
    /** other code **/
    private void initialize(final Builder builder) {
    this.someDependencyProvider =
    AppModule_SomeDependencyFactory.create(builder.appModule);
    }
    }
    (Generated)

    View Slide

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

    View Slide

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

    View Slide

  39. @ragdroid
    @droidconDE
    CASE 2
    DEPENDENCY WITH SCOPE

    View Slide

  40. AppModule
    @Module
    public class AppModule {
    @Provides
    @Singleton
    SomeDependency applicationProvider() {
    return new SomeDependency;
    }
    }

    View Slide

  41. AppModule
    @Module
    public class AppModule {
    @Provides
    @Singleton
    SomeDependency applicationProvider() {
    return new SomeDependency;
    }
    }

    View Slide

  42. DaggerAppComponent
    @Generated
    public final class DaggerAppComponent implements AppComponent {
    private Provider someDependencyProvider;
    /** other code **/
    private void initialize(final Builder builder) {
    this.someDependencyProvider =
    DoubleCheck.provider(
    AppModule_SomeDependencyFactory.create(builder.appModule));
    }
    }
    (Generated)

    View Slide

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

    View Slide

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

    View Slide

  45. DoubleCheck
    Memoizes value using Double-Check idiom.
    (dagger.internal)

    View Slide

  46. 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)

    View Slide

  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)

    View Slide

  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)

    View Slide

  49. Take Aways
    • DONT “Scope All the Things!”
    • Scoping has overheads.
    • By-default no Scope.
    • Scope only when needed
    • Like for Heavy Mutable Objects

    View Slide

  50. @ragdroid
    @droidconDE
    @REUSABLE

    View Slide

  51. @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.

    View Slide

  52. ReusableComponent

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

    View Slide

  53. ReusableComponent

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

    View Slide

  54. SomeObject
    @Reusable
    public class SomeObject {
    @Inject
    public SomeObject() {
    }
    }

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  58. SingleCheck
    Memoizes value using simple lazy initialization and caching
    (dagger.internal)

    View Slide

  59. Memoizes value using simple lazy initialization and caching
    public T get() {


    Provider providerReference = provider;

    if (instance == UNINITIALIZED) {

    instance = providerReference.get();

    provider = null;

    }

    return (T) instance;

    }
    (dagger.internal)
    SingleCheck

    View Slide

  60. Memoizes value using simple lazy initialization and caching
    public T get() {


    Provider providerReference = provider;

    if (instance == UNINITIALIZED) {

    instance = providerReference.get();

    provider = null;

    }

    return (T) instance;

    }
    (dagger.internal)
    SingleCheck

    View Slide

  61. No Scope vs @Singleton vs @Reusable
    • Not Heavy : No Scope
    • Heavy mutable object : @Singleton
    • Heavy immutable object : @Reusable


    View Slide

  62. @ragdroid
    @droidconDE
    GOD APP MODULE

    View Slide

  63. @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();
    }

    View Slide

  64. @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();
    }

    View Slide

  65. @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();
    }

    View Slide

  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
    God Module
    God App Module
    @Component(modules =
    AppModule.class)
    @Singleton
    public interface
    AppComponent {
    Application
    application();
    }

    View Slide

  67. @ragdroid
    @droidconDE
    God App Module
    How To Improve?

    View Slide

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

    View Slide

  69. @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

    View Slide

  70. @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();
    }

    View Slide

  71. @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)

    View Slide

  72. @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

    View Slide

  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)
    @Module(
    includes = ApiModule.class)
    AppModule
    OR
    AppComponent

    View Slide

  74. @ragdroid
    @droidconDE
    Splitting App Module

    View Slide

  75. @ragdroid
    @droidconDE
    How to Improve?
    • Better Scope Management
    • More modularity
    • Custom Scopes :
    • @UserScope
    • @ActivityScope
    • @FragmentScope

    View Slide

  76. @ragdroid
    @droidconDE
    Custom Scopes

    View Slide

  77. @ragdroid
    @droidconDE
    Custom Scopes
    Multiple Components

    View Slide

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

    View Slide

  79. COMPONENT
    DEPENDENCIES

    View Slide

  80. @ragdroid
    @droidconDE
    POKEMON APP

    View Slide

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

    View Slide

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

    View Slide

  83. 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

    View Slide

  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
    Inventory
    Application

    View Slide

  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
    Log-Out
    Inventory
    Application

    View Slide

  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
    jigglypuff
    Inventory
    Application

    View Slide

  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
    Inventory
    Application

    View Slide

  88. Pokemon App

    View Slide

  89. @ragdroid
    @droidconDE
    SUB COMPONENT
    VS
    DEPENDENT COMPONENT

    View Slide

  90. <>
    AppComponent
    schedulerProvider
    @Singleton

    View Slide

  91. AppComponentImpl
    • schedulerProvider() : @Singleton
    • userManager : @Singleton
    LoginComponentImpl
    <>
    AppComponent
    schedulerProvider
    Login Sub Component
    @Singleton
    @ActivityScope

    View Slide

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

    View Slide

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

    View Slide

  94. @ragdroid
    @droidconDE
    APP COMPONENT

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  98. @ragdroid
    @droidconDE
    DAHAKA
    APPLICATION

    View Slide

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

    View Slide

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

    View Slide

  101. DEPENDENT
    COMPONENTS

    View Slide

  102. @ragdroid
    @droidconDE
    USER
    COMPONENT

    View Slide

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

    }
    }
    UserComponent

    View Slide

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

    }
    }
    UserComponent

    View Slide

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

    }
    }
    UserComponent

    View Slide

  106. Binding Pokemon
    • Two ways of Providing / Binding Pokemon to graph
    1. UserModule Constructor
    2. @Component.Builder with @BindsInstance

    View Slide


  107. @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

    View Slide


  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

    View Slide


  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

    View Slide

  110. @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

    View Slide

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

    }
    }
    UserComponent @BindsInstance

    View Slide

  112. @ragdroid
    @droidconDE
    USER
    MANAGER

    View Slide

  113. @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

    View Slide

  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

    View Slide

  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

    View Slide

  116. @ragdroid
    @droidconDE
    DAGGER
    USER COMPONENT
    (Generated)

    View Slide

  117. public final class DaggerUserComponent implements UserComponent {
    private Provider schedulerProvider;
    private void initialize(final Builder builder) {
    this.schedulerProvider =
    new AppComponent_schedulerProvider(builder.appComponent);

    }
    private static class AppComponent_schedulerProvider
    implements Provider {
    private final AppComponent appComponent;
    @Override
    public BaseSchedulerProvider get() {
    return appComponent.schedulerProvider();
    }

    }
    }
    DaggerUserComponent (Generated)

    View Slide

  118. public final class DaggerUserComponent implements UserComponent {
    private Provider schedulerProvider;
    private void initialize(final Builder builder) {
    this.schedulerProvider =
    new AppComponent_schedulerProvider(builder.appComponent);

    }
    private static class AppComponent_schedulerProvider
    implements Provider {
    private final AppComponent appComponent;
    @Override
    public BaseSchedulerProvider get() {
    return appComponent.schedulerProvider();
    }

    }
    }
    DaggerUserComponent (Generated)

    View Slide

  119. public final class DaggerUserComponent implements UserComponent {
    private Provider schedulerProvider;
    private void initialize(final Builder builder) {
    this.schedulerProvider =
    new AppComponent_schedulerProvider(builder.appComponent);

    }
    private static class AppComponent_schedulerProvider
    implements Provider {
    private final AppComponent appComponent;
    @Override
    public BaseSchedulerProvider get() {
    return appComponent.schedulerProvider();
    }

    }
    }
    DaggerUserComponent (Generated)

    View Slide

  120. public final class DaggerUserComponent implements UserComponent {
    private Provider schedulerProvider;
    private void initialize(final Builder builder) {
    this.schedulerProvider =
    new AppComponent_schedulerProvider(builder.appComponent);

    }
    private static class AppComponent_schedulerProvider
    implements Provider {
    private final AppComponent appComponent;
    @Override
    public BaseSchedulerProvider get() {
    return appComponent.schedulerProvider();
    }

    }
    }
    DaggerUserComponent (Generated)

    View Slide

  121. public final class DaggerUserComponent implements UserComponent {
    private Provider schedulerProvider;
    private void initialize(final Builder builder) {
    this.schedulerProvider =
    new AppComponent_schedulerProvider(builder.appComponent);

    }
    private static class AppComponent_schedulerProvider
    implements Provider {
    private final AppComponent appComponent;
    @Override
    public BaseSchedulerProvider get() {
    return appComponent.schedulerProvider();
    }

    }
    }
    DaggerUserComponent (Generated)

    View Slide

  122. public final class DaggerUserComponent implements UserComponent {
    private Provider schedulerProvider;
    private void initialize(final Builder builder) {
    this.schedulerProvider =
    new AppComponent_schedulerProvider(builder.appComponent);

    }
    private static class AppComponent_schedulerProvider
    implements Provider {
    private final AppComponent appComponent;
    @Override
    public BaseSchedulerProvider get() {
    return appComponent.schedulerProvider();
    }

    }
    }
    DaggerUserComponent (Generated)

    View Slide

  123. SUB
    COMPONENTS

    View Slide

  124. @ragdroid
    @droidconDE
    LOGIN
    SUBCOMPONENT

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  130. @ragdroid
    @droidconDE
    LOGIN
    ACTIVITY

    View Slide

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

    }
    LoginActivity

    View Slide

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

    }
    LoginActivity

    View Slide

  133. @ragdroid
    @droidconDE
    DAGGER
    APP COMPONENT
    (Generated)

    View Slide

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

    }
    }
    DaggerAppComponent (Generated)

    View Slide

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

    }
    }
    DaggerAppComponent (Generated)

    View Slide

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

    }
    }
    DaggerAppComponent (Generated)

    View Slide

  137. @ragdroid
    @droidconDE
    SUB COMPONENT
    VS
    DEPENDENT COMPONENT

    View Slide

  138. <>
    AppComponent
    fun schedulerProvider()
    @Singleton

    View Slide

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

    View Slide

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

    View Slide

  141. DaggerUserComponent
    • schedulerProvider
    • pokemon
    DaggerAppComponent
    • schedulerProvider() : @Singleton
    • userManager : @Singleton
    LoginComponentImpl
    <>
    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.

    View Slide

  142. DaggerUserComponent
    • schedulerProvider
    • pokemon
    DaggerAppComponent
    • schedulerProvider() : @Singleton
    • userManager : @Singleton
    LoginComponentImpl
    <>
    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.

    View Slide

  143. @ragdroid
    @droidconDE
    Custom Scope Advantages
    • Dependency Lifecycle Management
    • Modularized code

    View Slide

  144. @ragdroid
    @droidconDE
    Some Limitations
    • Repetitive Injection code
    • Class knows about it’s Injector

    View Slide

  145. @ragdroid
    @droidconDE
    Some Limitations
    Dagger 2 Android

    View Slide

  146. INTERMEDIATE CONCEPTS
    “DEFEAT THE DAHAKA”

    View Slide

  147. @ragdroid
    @droidconDE
    @BINDS

    View Slide

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

    View Slide

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

    View Slide

  150. @ragdroid
    @droidconDE
    MULTIBINDING

    View Slide

  151. MultiBinding @IntoSet
    @Provides String - “Hello”
    @Provides String - “Hi”
    @Provides String - “How are you?”

    View Slide

  152. @Provides String - “Hello”
    @Provides String - “Hi”
    @Provides String - “How are you?”
    @IntoSet
    @IntoSet
    @IntoSet
    MultiBinding @IntoSet

    View Slide

  153. @Provides Set
    {“Hello”, “Hi”, “How are you?”}
    MultiBinding @IntoSet

    View Slide

  154. MultiBinding @IntoMap
    <>
    Contract.Presenter
    MapPresenter JustPresenter TakePresenter

    View Slide

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

    View Slide

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

    View Slide

  157. MultiBinding @IntoMap
    @Provides MapPresenter mapPresenter
    @Provides JustPresenter justPresenter
    @Provides TakePresenter takePresenter
    @IntoMap
    @IntoMap
    @IntoMap
    @ClassKey(MapPresenter.java)
    @ClassKey(JustPresenter.java)
    @ClassKey(TakePresenter.java)

    View Slide

  158. MultiBinding @IntoMap
    @Provides
    Map
    {
    mapPresenter,
    justPresenter,
    takePresenter
    }

    View Slide

  159. DAGGER 2
    ANDROID
    “BEFRIEND THE BEAST”

    View Slide

  160. @ragdroid
    @droidconDE
    DAHAKA
    APPLICATION

    View Slide

  161. class DahakaApplication : Application(), HasActivityInjector {
    @Inject internal lateinit var
    activityInjector: DispatchingAndroidInjector

    override fun activityInjector(): AndroidInjector {
    return activityInjector
    }

    }
    DahakaApplication

    View Slide

  162. class DahakaApplication : Application(), HasActivityInjector {
    @Inject internal lateinit var
    activityInjector: DispatchingAndroidInjector

    override fun activityInjector(): AndroidInjector {
    return activityInjector
    }

    }
    DahakaApplication

    View Slide

  163. class DahakaApplication : Application(), HasActivityInjector {
    @Inject internal lateinit var
    activityInjector: DispatchingAndroidInjector

    override fun activityInjector(): AndroidInjector {
    return activityInjector
    }

    }
    DahakaApplication

    View Slide

  164. class DahakaApplication : Application(), HasActivityInjector {
    @Inject internal lateinit var
    activityInjector: DispatchingAndroidInjector

    override fun activityInjector(): AndroidInjector {
    return activityInjector
    }

    }
    DahakaApplication

    View Slide

  165. public interface HasActivityInjector {
    AndroidInjector activityInjector();
    }
    HasActivityInjector

    View Slide

  166. HasActivityInjector
    • A simple interface.
    • Implementing class “Has” ActivityInjector.
    public interface HasActivityInjector {
    AndroidInjector activityInjector();
    }

    View Slide

  167. DispatchingAndroidInjector : AndroidInjector

    View Slide

  168. DispatchingAndroidInjector : AndroidInjector
    • Injects members for Android types : Activity, Fragment, etc
    • Has a Map> injectorFactories.

    View Slide

  169. Provider
    LoginActivity.class
    Class Provider>
    DispatchingAndroidInject
    • 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> injectorFactories.
    DispatchingAndroidInjector : AndroidInjector

    View Slide

  170. @ragdroid
    @droidconDE
    APP COMPONENT

    View Slide

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

    }
    AppComponent

    View Slide

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

    }
    AppComponent

    View Slide

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

    View Slide

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

    View Slide

  175. @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

    View Slide

  176. @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

    View Slide

  177. @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 {
    @Subcomponent.Builder
    abstract class Builder extends AndroidInjector.Builder {}
    }
    }
    LoginBindingModule(Generated)

    View Slide

  178. @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 {
    @Subcomponent.Builder
    abstract class Builder extends AndroidInjector.Builder {}
    }
    }
    LoginBindingModule(Generated)

    View Slide

  179. @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 {
    @Subcomponent.Builder
    abstract class Builder extends AndroidInjector.Builder {}
    }
    }
    LoginBindingModule(Generated)

    View Slide

  180. @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 {
    @Subcomponent.Builder
    abstract class Builder extends AndroidInjector.Builder {}
    }
    }
    LoginBindingModule(Generated)

    View Slide

  181. @ragdroid
    @droidconDE
    LOGIN ACTIVITY

    View Slide

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

    View Slide

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

    View Slide

  184. AndroidInjection.inject(LoginActivity)
    AndroidInjection.inje

    View Slide

  185. AndroidInjection.inject(LoginActivity)
    AndroidInjection.inje
    AndroidInjection

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  190. @ragdroid
    @droidconDE
    BEFRIEND THE BEAST
    “You can not change your fate,
    No droid can.”

    View Slide

  191. AndroidInjection.inject(LoginActivity)

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  196. DispatchingAndroidInjector.inject(LoginActivity)
    injectorFactories
    .get(LoginActivity.class)
    DispatchingAndroidInjector : AndroidInjector

    View Slide

  197. DispatchingAndroidInjector : AndroidInjector
    Factory : LoginSubcomponent.Builder
    injectorFactories
    .get(LoginActivity.class)
    DispatchingAndroidInjector.inject(LoginActivity)
    builder
    .build()

    View Slide

  198. DispatchingAndroidInjector : AndroidInjector
    Factory : LoginSubcomponent.Builder
    component
    .inject(activity)
    LoginSubcomponent
    injectorFactories
    .get(LoginActivity.class)
    DispatchingAndroidInjector.inject(LoginActivity)
    builder
    .build()

    View Slide

  199. DispatchingAndroidInjector : AndroidInjector
    builder
    .build()
    Factory : LoginSubcomponent.Builder
    component
    .inject(activity)
    LoginSubcomponent
    DispatchingAndroidInjector.inject(LoginActivity)
    injectorFactories
    .get(LoginActivity.class)

    View Slide

  200. • DaggerApplication
    • DaggerActivity
    • DaggerBroadcastReceiver
    • DaggerContentProvider
    • DaggerFragment
    • DaggerIntentService
    • DaggerService
    Dagger Boilerplate classes

    View Slide

  201. 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

    View Slide

  202. @ragdroid
    @droidconDE
    Dagger 2 Android = Dahaka
    • D
    • A
    • H
    • A
    • K
    • A
    Dagger
    Android
    HasActivityInjector
    AndroidInjection
    Keys
    AndroidInjector

    View Slide

  203. @ragdroid
    @droidconDE
    Dagger 2 Android
    “You can not change your fate,
    No droid can”
    Let’s befriend the beast instead.

    View Slide

  204. 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)

    View Slide

  205. 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

    View Slide

  206. 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

    View Slide

  207. @ragdroid
    @droidconDE
    CUT
    SCENES

    View Slide

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

    View Slide

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

    View Slide

  210. FUELED
    http://fueled.com/garima
    [email protected]
    THANK YOU

    View Slide

  211. FUELED
    http://fueled.com/garima
    [email protected]
    Q & A
    @ragdroid

    View Slide