Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

Garima Jain @ragdroid

Slide 3

Slide 3 text

Garima Jain @ragdroid

Slide 4

Slide 4 text

Garima Jain @ragdroid

Slide 5

Slide 5 text

Garima Jain @ragdroid

Slide 6

Slide 6 text

Garima Jain @ragdroid

Slide 7

Slide 7 text

Garima Jain @ragdroid

Slide 8

Slide 8 text

@ragdroid @droidconDE

Slide 9

Slide 9 text

@ragdroid @droidconDE MVP Testing DataBinding Retrofit Dagger 2

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

ABOUT THE TALK

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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”

Slide 17

Slide 17 text

Who? • Assumption : Basic familiarity with Dagger • Intermediate

Slide 18

Slide 18 text

INTRODUCTION “CODES OF TIME”

Slide 19

Slide 19 text

@ragdroid @droidconDE Droid of Asia

Slide 20

Slide 20 text

@ragdroid @droidconDE public UserManager() {
 this.service = new PokemonService(); 
 } Droid of Asia

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

@ragdroid @droidconDE Dagger 1

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

@ragdroid @droidconDE Dagger 1 Disadvantages Dagger 2

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

SCOPES “FACE OF THE DAHAKA”

Slide 28

Slide 28 text

Scope • Annotation from javax.inject package • How long a scoped instance lives • What happens if : • No Scope specified? • Annotation is specified?

Slide 29

Slide 29 text

@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

Slide 30

Slide 30 text

@ragdroid @droidconDE @SINGLETON EXAMPLE

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

@ragdroid @droidconDE CASE 1 DEPENDENCY W/O SCOPE

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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)

Slide 37

Slide 37 text

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)

Slide 38

Slide 38 text

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)

Slide 39

Slide 39 text

@ragdroid @droidconDE CASE 2 DEPENDENCY WITH SCOPE

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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)

Slide 43

Slide 43 text

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)

Slide 44

Slide 44 text

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)

Slide 45

Slide 45 text

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)

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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)

Slide 48

Slide 48 text

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)

Slide 49

Slide 49 text

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)

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

@ragdroid @droidconDE @REUSABLE

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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)

Slide 57

Slide 57 text

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)

Slide 58

Slide 58 text

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)

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

@ragdroid @droidconDE GOD APP MODULE

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

@ragdroid @droidconDE God App Module How To Improve?

Slide 69

Slide 69 text

@ragdroid @droidconDE God App Module Splitting App Module

Slide 70

Slide 70 text

@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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

@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

Slide 74

Slide 74 text

@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

Slide 75

Slide 75 text

@ragdroid @droidconDE Splitting App Module

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

@ragdroid @droidconDE Custom Scopes

Slide 78

Slide 78 text

@ragdroid @droidconDE Custom Scopes Multiple Components

Slide 79

Slide 79 text

Multiple Components 1. Dependent Components 2. Sub-Components

Slide 80

Slide 80 text

COMPONENT DEPENDENCIES

Slide 81

Slide 81 text

@ragdroid @droidconDE POKEMON APP

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

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

Slide 89

Slide 89 text

Pokemon App

Slide 90

Slide 90 text

@ragdroid @droidconDE SUB COMPONENT VS DEPENDENT COMPONENT

Slide 91

Slide 91 text

<> AppComponent schedulerProvider @Singleton

Slide 92

Slide 92 text

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

Slide 93

Slide 93 text

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

Slide 94

Slide 94 text

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

Slide 95

Slide 95 text

@ragdroid @droidconDE APP COMPONENT

Slide 96

Slide 96 text

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

Slide 97

Slide 97 text

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

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

@ragdroid @droidconDE DAHAKA APPLICATION

Slide 100

Slide 100 text

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

Slide 101

Slide 101 text

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

Slide 102

Slide 102 text

DEPENDENT COMPONENTS

Slide 103

Slide 103 text

@ragdroid @droidconDE USER COMPONENT

Slide 104

Slide 104 text

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

Slide 105

Slide 105 text

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

Slide 106

Slide 106 text

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

Slide 107

Slide 107 text

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

Slide 108

Slide 108 text


 @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

Slide 109

Slide 109 text


 @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

Slide 110

Slide 110 text


 @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

Slide 111

Slide 111 text

@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

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

@ragdroid @droidconDE USER MANAGER

Slide 114

Slide 114 text

@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

Slide 115

Slide 115 text

@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

Slide 116

Slide 116 text

@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

Slide 117

Slide 117 text

@ragdroid @droidconDE DAGGER USER COMPONENT (Generated)

Slide 118

Slide 118 text

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)

Slide 119

Slide 119 text

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)

Slide 120

Slide 120 text

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)

Slide 121

Slide 121 text

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)

Slide 122

Slide 122 text

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)

Slide 123

Slide 123 text

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)

Slide 124

Slide 124 text

SUB COMPONENTS

Slide 125

Slide 125 text

@ragdroid @droidconDE LOGIN SUBCOMPONENT

Slide 126

Slide 126 text

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

Slide 127

Slide 127 text

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

Slide 128

Slide 128 text

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

Slide 129

Slide 129 text

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

Slide 130

Slide 130 text

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

Slide 131

Slide 131 text

@ragdroid @droidconDE LOGIN ACTIVITY

Slide 132

Slide 132 text

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

Slide 133

Slide 133 text

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

Slide 134

Slide 134 text

@ragdroid @droidconDE DAGGER APP COMPONENT (Generated)

Slide 135

Slide 135 text

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)

Slide 136

Slide 136 text

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)

Slide 137

Slide 137 text

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)

Slide 138

Slide 138 text

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)

Slide 139

Slide 139 text

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)

Slide 140

Slide 140 text

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)

Slide 141

Slide 141 text

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)

Slide 142

Slide 142 text

@ragdroid @droidconDE SUB COMPONENT VS DEPENDENT COMPONENT

Slide 143

Slide 143 text

<> AppComponent fun schedulerProvider() @Singleton

Slide 144

Slide 144 text

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

Slide 145

Slide 145 text

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

Slide 146

Slide 146 text

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.

Slide 147

Slide 147 text

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.

Slide 148

Slide 148 text

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

Slide 149

Slide 149 text

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

Slide 150

Slide 150 text

@ragdroid @droidconDE Some Limitations Dagger 2 Android

Slide 151

Slide 151 text

INTERMEDIATE CONCEPTS “DEFEAT THE DAHAKA”

Slide 152

Slide 152 text

@ragdroid @droidconDE @BINDS

Slide 153

Slide 153 text

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

Slide 154

Slide 154 text

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

Slide 155

Slide 155 text

@ragdroid @droidconDE MULTIBINDING

Slide 156

Slide 156 text

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

Slide 157

Slide 157 text

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

Slide 158

Slide 158 text

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

Slide 159

Slide 159 text

MultiBinding @IntoMap <> Contract.Presenter MapPresenter JustPresenter TakePresenter

Slide 160

Slide 160 text

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

Slide 161

Slide 161 text

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

Slide 162

Slide 162 text

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

Slide 163

Slide 163 text

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

Slide 164

Slide 164 text

DAGGER 2 ANDROID “BEFRIEND THE BEAST”

Slide 165

Slide 165 text

@ragdroid @droidconDE DAHAKA APPLICATION

Slide 166

Slide 166 text

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

Slide 167

Slide 167 text

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

Slide 168

Slide 168 text

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

Slide 169

Slide 169 text

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

Slide 170

Slide 170 text

public interface HasActivityInjector { AndroidInjector activityInjector(); } HasActivityInjector

Slide 171

Slide 171 text

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

Slide 172

Slide 172 text

HasActivityInjector <> HasActivityInjector fun activityInjector() : AndroidInjector

Slide 173

Slide 173 text

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

Slide 174

Slide 174 text

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

Slide 175

Slide 175 text

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

Slide 176

Slide 176 text

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

Slide 177

Slide 177 text

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.

Slide 178

Slide 178 text

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

Slide 179

Slide 179 text

@ragdroid @droidconDE APP COMPONENT

Slide 180

Slide 180 text

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

Slide 181

Slide 181 text

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

Slide 182

Slide 182 text

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

Slide 183

Slide 183 text

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

Slide 184

Slide 184 text

@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

Slide 185

Slide 185 text

@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

Slide 186

Slide 186 text

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

Slide 187

Slide 187 text

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

Slide 188

Slide 188 text

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

Slide 189

Slide 189 text

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

Slide 190

Slide 190 text

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

Slide 191

Slide 191 text

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

Slide 192

Slide 192 text

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

Slide 193

Slide 193 text

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

Slide 194

Slide 194 text

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

Slide 195

Slide 195 text

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

Slide 196

Slide 196 text

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

Slide 197

Slide 197 text

@ragdroid @droidconDE LOGIN ACTIVITY

Slide 198

Slide 198 text

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

Slide 199

Slide 199 text

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

Slide 200

Slide 200 text

AndroidInjection.inject(LoginActivity) AndroidInjection.inje

Slide 201

Slide 201 text

AndroidInjection.inject(LoginActivity) AndroidInjection.inje AndroidInjection

Slide 202

Slide 202 text

AndroidInjection.inject(LoginActivity) AndroidInjection.inje AndroidInjection DaggerAppComponent

Slide 203

Slide 203 text

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

Slide 204

Slide 204 text

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

Slide 205

Slide 205 text

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

Slide 206

Slide 206 text

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

Slide 207

Slide 207 text

AndroidInjection.inject(LoginActivity)

Slide 208

Slide 208 text

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

Slide 209

Slide 209 text

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

Slide 210

Slide 210 text

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

Slide 211

Slide 211 text

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

Slide 212

Slide 212 text

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

Slide 213

Slide 213 text

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

Slide 214

Slide 214 text

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

Slide 215

Slide 215 text

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

Slide 216

Slide 216 text

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

Slide 217

Slide 217 text

@ragdroid @droidconDE TESTING WITH DAGGER 2 ANDROID

Slide 218

Slide 218 text

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

Slide 219

Slide 219 text

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

Slide 220

Slide 220 text

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

Slide 221

Slide 221 text

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

Slide 222

Slide 222 text

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

Slide 223

Slide 223 text

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

Slide 224

Slide 224 text

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

Slide 225

Slide 225 text

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

Slide 226

Slide 226 text

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)

Slide 227

Slide 227 text

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

Slide 228

Slide 228 text

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

Slide 229

Slide 229 text

@ragdroid @droidconDE CUT SCENES

Slide 230

Slide 230 text

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

Slide 231

Slide 231 text

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

Slide 232

Slide 232 text

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

Slide 233

Slide 233 text

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