$30 off During Our Annual Pro Sale. View Details »

Dagger 2 Android : Defeat the Dahaka

ragdroid
September 03, 2017

Dagger 2 Android : Defeat the Dahaka

Presentation for Droidcon Berlin, 2017.

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

ragdroid

September 03, 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 javax.inject package
    • How long a scoped instance lives
    • What happens if :
    • No Scope specified?
    • Annotation is specified?

    View Slide

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

    View Slide

  30. @ragdroid
    @droidconDE
    @SINGLETON
    EXAMPLE

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  39. @ragdroid
    @droidconDE
    CASE 2
    DEPENDENCY WITH SCOPE

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  46. DoubleCheck
    Memoizes value using Double-Check idiom.
    (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. 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

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

  51. @ragdroid
    @droidconDE
    @REUSABLE

    View Slide

  52. @Reusable
    • Limit the instantiation.
    • Use when Exact same instance not needed.
    • Not tied to any component or subcomponent.
    • Can Have multiple sub-components caching different instances.
    • Use for heavy immutable dependencies.

    View Slide

  53. ReusableComponent

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

    View Slide

  54. ReusableComponent

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

    View Slide

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

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

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

    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. Memoizes value using simple lazy initialization
    public T get() {


    Provider providerReference = provider;

    if (instance == UNINITIALIZED) {

    instance = providerReference.get();

    provider = null;

    }

    return (T) instance;

    }
    (dagger.internal)
    SingleCheck

    View Slide

  62. @Singleton vs @Reusable
    • Heavy mutable object : @Singleton
    • Heavy immutable object : @Reusable


    View Slide

  63. @ragdroid
    @droidconDE
    GOD APP MODULE

    View Slide

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

    View Slide

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

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    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)
    OR
    AppComponent

    View Slide

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

    View Slide

  75. @ragdroid
    @droidconDE
    Splitting App Module

    View Slide

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

    View Slide

  77. @ragdroid
    @droidconDE
    Custom Scopes

    View Slide

  78. @ragdroid
    @droidconDE
    Custom Scopes
    Multiple Components

    View Slide

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

    View Slide

  80. COMPONENT
    DEPENDENCIES

    View Slide

  81. @ragdroid
    @droidconDE
    POKEMON APP

    View Slide

  82. AppComponent (@Singleton)
    UserComponent
    (@UserScope)
    UserComponent
    @UserScope
    Login
    Component
    @ActivityScope
    Home
    Component
    Items
    Component
    Login
    Component
    Home
    Component
    Items
    Component
    Fragments Fragments
    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
    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
    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
    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
    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
    Application

    View Slide

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

    View Slide

  89. Pokemon App

    View Slide

  90. @ragdroid
    @droidconDE
    SUB COMPONENT
    VS
    DEPENDENT COMPONENT

    View Slide

  91. <>
    AppComponent
    schedulerProvider
    @Singleton

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  95. @ragdroid
    @droidconDE
    APP COMPONENT

    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. @Singleton
    @Component(modules = arrayOf(AppModule::class, ApiModule::class))
    interface AppComponent {
    fun loginBuilder(): LoginComponent.Builder
    fun schedulerProvider(): BaseSchedulerProvider
    }
    AppComponent

    View Slide

  99. @ragdroid
    @droidconDE
    DAHAKA
    APPLICATION

    View Slide

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

    View Slide

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

    View Slide

  102. DEPENDENT
    COMPONENTS

    View Slide

  103. @ragdroid
    @droidconDE
    USER
    COMPONENT

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

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

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

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

    }
    }
    User Component @Component.Builder

    View Slide

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

    }
    }
    UserComponent @BindsInstance

    View Slide

  113. @ragdroid
    @droidconDE
    USER
    MANAGER

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

  117. @ragdroid
    @droidconDE
    DAGGER
    USER COMPONENT
    (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. 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

  124. SUB
    COMPONENTS

    View Slide

  125. @ragdroid
    @droidconDE
    LOGIN
    SUBCOMPONENT

    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. @ActivityScope
    @Subcomponent(modules = arrayOf(LoginModule::class))
    interface LoginComponent {
    @Subcomponent.Builder
    interface Builder {
    @BindsInstance
    fun loginActivity(loginActivity: LoginActivity): Builder
    }
    }
    LoginComponent

    View Slide

  131. @ragdroid
    @droidconDE
    LOGIN
    ACTIVITY

    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. class LoginActivity {
    private lateinit var loginComponent: LoginComponent
    override fun initDagger(appComponent: AppComponent) {
    loginComponent = appComponent
    .loginBuilder()
    .loginActivity(this)
    .build()
    }

    }
    LoginActivity

    View Slide

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

    View Slide

  135. public final class DaggerAppComponent implements AppComponent {
    this.loginBuilderProvider =
    new Factory() {
    @Override
    public LoginComponent.Builder get() {
    return new LoginComponentBuilder();
    }
    };
    }
    private final class LoginComponentBuilder implements LoginComponent.Builder {

    }
    private final class LoginComponentImpl implements LoginComponent {
    private LoginComponentImpl(LoginComponentBuilder builder) {
    assert builder != null;
    initialize(builder);
    }

    }
    }
    DaggerAppComponent (Generated)

    View Slide

  136. public final class DaggerAppComponent implements AppComponent {
    this.loginBuilderProvider =
    new Factory() {
    @Override
    public LoginComponent.Builder get() {
    return new LoginComponentBuilder();
    }
    };
    }
    private final class LoginComponentBuilder implements LoginComponent.Builder {

    }
    private final class LoginComponentImpl implements LoginComponent {
    private LoginComponentImpl(LoginComponentBuilder builder) {
    assert builder != null;
    initialize(builder);
    }

    }
    }
    DaggerAppComponent (Generated)

    View Slide

  137. public final class DaggerAppComponent implements AppComponent {
    this.loginBuilderProvider =
    new Factory() {
    @Override
    public LoginComponent.Builder get() {
    return new LoginComponentBuilder();
    }
    };
    }
    private final class LoginComponentBuilder implements LoginComponent.Builder {

    }
    private final class LoginComponentImpl implements LoginComponent {
    private LoginComponentImpl(LoginComponentBuilder builder) {
    assert builder != null;
    initialize(builder);
    }

    }
    }
    DaggerAppComponent (Generated)

    View Slide

  138. public final class DaggerAppComponent implements AppComponent {
    this.loginBuilderProvider =
    new Factory() {
    @Override
    public LoginComponent.Builder get() {
    return new LoginComponentBuilder();
    }
    };
    }
    private final class LoginComponentBuilder implements LoginComponent.Builder {

    }
    private final class LoginComponentImpl implements LoginComponent {
    private LoginComponentImpl(LoginComponentBuilder builder) {
    assert builder != null;
    initialize(builder);
    }

    }
    }
    DaggerAppComponent (Generated)

    View Slide

  139. public final class DaggerAppComponent implements AppComponent {
    this.loginBuilderProvider =
    new Factory() {
    @Override
    public LoginComponent.Builder get() {
    return new LoginComponentBuilder();
    }
    };
    }
    private final class LoginComponentBuilder implements LoginComponent.Builder {

    }
    private final class LoginComponentImpl implements LoginComponent {
    private LoginComponentImpl(LoginComponentBuilder builder) {
    assert builder != null;
    initialize(builder);
    }

    }
    }
    DaggerAppComponent (Generated)

    View Slide

  140. public final class DaggerAppComponent implements AppComponent {
    this.loginBuilderProvider =
    new Factory() {
    @Override
    public LoginComponent.Builder get() {
    return new LoginComponentBuilder();
    }
    };
    }
    private final class LoginComponentBuilder implements LoginComponent.Builder {

    }
    private final class LoginComponentImpl implements LoginComponent {
    private LoginComponentImpl(LoginComponentBuilder builder) {
    assert builder != null;
    initialize(builder);
    }

    }
    }
    DaggerAppComponent (Generated)

    View Slide

  141. public final class DaggerAppComponent implements AppComponent {
    this.loginBuilderProvider =
    new Factory() {
    @Override
    public LoginComponent.Builder get() {
    return new LoginComponentBuilder();
    }
    };
    }
    private final class LoginComponentBuilder implements LoginComponent.Builder {

    }
    private final class LoginComponentImpl implements LoginComponent {
    private LoginComponentImpl(LoginComponentBuilder builder) {
    assert builder != null;
    initialize(builder);
    }

    }
    }
    DaggerAppComponent (Generated)

    View Slide

  142. @ragdroid
    @droidconDE
    SUB COMPONENT
    VS
    DEPENDENT COMPONENT

    View Slide

  143. <>
    AppComponent
    fun schedulerProvider()
    @Singleton

    View Slide

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

    View Slide

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

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

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

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

    View Slide

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

    View Slide

  150. @ragdroid
    @droidconDE
    Some Limitations
    Dagger 2 Android

    View Slide

  151. INTERMEDIATE CONCEPTS
    “DEFEAT THE DAHAKA”

    View Slide

  152. @ragdroid
    @droidconDE
    @BINDS

    View Slide

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

    View Slide

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

  155. @ragdroid
    @droidconDE
    MULTIBINDING

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

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

    View Slide

  164. DAGGER 2
    ANDROID
    “BEFRIEND THE BEAST”

    View Slide

  165. @ragdroid
    @droidconDE
    DAHAKA
    APPLICATION

    View Slide

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

    override fun activityInjector(): AndroidInjector {
    return activityInjector
    }

    }
    DahakaApplication

    View Slide

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

    override fun activityInjector(): AndroidInjector {
    return activityInjector
    }

    }
    DahakaApplication

    View Slide

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

    override fun activityInjector(): AndroidInjector {
    return activityInjector
    }

    }
    DahakaApplication

    View Slide

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

    override fun activityInjector(): AndroidInjector {
    return activityInjector
    }

    }
    DahakaApplication

    View Slide

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

    View Slide

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

    View Slide

  172. HasActivityInjector
    <>
    HasActivityInjector
    fun activityInjector() :
    AndroidInjector

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  177. DispatchingAndroidInjector
    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.

    View Slide

  178. Provider
    HomeActivity.class
    ItemsActivity.class Provider
    Provider
    ProfileFragment.class
    MovesFragment.class Provider
    Class Provider>
    Provider
    StatsFragment.class
    DispatchingAndroidInjector
    Provider
    LoginActivity.class
    Class Provider>
    DispatchingAndroidInject
    DispatchingAndroidInject

    View Slide

  179. @ragdroid
    @droidconDE
    APP COMPONENT

    View Slide

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

    }
    AppComponent

    View Slide

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

    }
    AppComponent

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  185. @Module
    abstract class AppBindingModule {
    @ContributesAndroidInjector(modules = arrayOf(LoginModule::class))
    @ActivityScope
    internal abstract fun loginActivity(): LoginActivity
    }
    AppBindingModule
    @Module
    abstract class LoginModule {
    @Binds
    abstract fun provideLoginPresenter(loginPresenter: LoginPresenter):
    LoginContract.Presenter
    }
    LoginModule

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    }
    AppComponent

    View Slide

  192. @Beta
    @Module(includes = AndroidInjectionModule.class)
    public abstract class AndroidSupportInjectionModule {
    @Multibinds
    abstract Map, AndroidInjector.Factory extends Fragment>>
    supportFragmentInjectorFactories();
    private AndroidSupportInjectionModule() {}
    }
    @Beta
    @Module
    public abstract class AndroidInjectionModule {
    @Multibinds
    abstract Map, AndroidInjector.Factory extends Activity>>
    activityInjectorFactories();
    @Multibinds
    abstract Map, AndroidInjector.Factory extends Fragment>>
    fragmentInjectorFactories();

    }
    AndroidSupportInjectionModule (dagger.android)

    View Slide

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

    }
    AndroidSupportInjectionModule (dagger.android)

    View Slide

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

    }
    AndroidSupportInjectionModule (dagger.android)

    View Slide

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

    }
    AndroidSupportInjectionModule (dagger.android)

    View Slide

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

    }
    AndroidSupportInjectionModule (dagger.android)

    View Slide

  197. @ragdroid
    @droidconDE
    LOGIN ACTIVITY

    View Slide

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

    View Slide

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

    View Slide

  200. AndroidInjection.inject(LoginActivity)
    AndroidInjection.inje

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  207. AndroidInjection.inject(LoginActivity)

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  217. @ragdroid
    @droidconDE
    TESTING
    WITH
    DAGGER 2 ANDROID

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  223. Demo Code
    • Dahaka Demo :
    https://github.com/ragdroid/Dahaka
    • Branches :
    • dagger-android : Pokemon app using dagger-android (With Tests, Fragments)
    • dagger-android-dependent-comp : dagger-android with Dependent Component
    • dagger-android-dependent-comp-kotlin : In Kotlin
    • subcomponent : UserComponent as subcomponent
    • dependent-component : UserComponent as dependent component
    • dependent-component-kotlin : In Kotlin

    View Slide

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

    View Slide

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

    View Slide

  226. Acknowledgements
    • Dagger Recipies : Miroslaw Stanek (@froger_mcs)
    https://about.me/froger_mcs
    • todo-mvp-dagger : Mike Nakhimovich (@friendlyMikhail )
    https://github.com/googlesamples/android-architecture/tree/todo-mvp-dagger
    • Android Dialogs : Mike Nakhimovich
    https://www.youtube.com/watch?v=KwRXQ6nT7jQ
    • Proof Reading : Ritesh Gupta (@_riteshhh)
    • Migrate to Kotlin : Ravindra Kumar (@ravidsrk)

    View Slide

  227. What Next?
    • Dagger Documentation :
    https://google.github.io/dagger//
    • todo-mvp-dagger : Mike Nakhimovich (@friendlyMikhail )
    https://github.com/googlesamples/android-architecture/tree/todo-mvp-dagger
    • Android Dialogs : Mike Nakhimovich
    https://www.youtube.com/watch?v=KwRXQ6nT7jQ
    • Dagger Example
    https://github.com/ragdroid/Dahaka
    • Testing article
    https://android.jlelse.eu/testing-your-app-with-dagger-2-c91cdc0860fb
    • Dagger and the Dahaka Series :
    https://medium.com/@ragdroid

    View Slide

  228. Other References
    • Theme : Prince of Persia https://en.wikipedia.org/wiki/Prince_of_Persia
    • Dahaka https://files.gamebanana.com/img/ico/sprays/dahaka.png
    • Dagger https://in.pinterest.com/pin/397442735844321339/
    • Android http://www.pngmart.com/files/4/Android-PNG-Image.png

    View Slide

  229. @ragdroid
    @droidconDE
    CUT
    SCENES

    View Slide

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

    View Slide

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

    View Slide

  232. FUELED
    http://fueled.com/garima
    [email protected]
    VIELEN DANK
    THANK YOU

    View Slide

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

    View Slide