Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

ABOUT THE TALK

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

Agenda • Scopes - “Face of the Dahaka” • @Singleton Scopes • @Reusable Scopes • Custom Scopes • Component Dependencies - “Unleash the Beast” • Dependent Component • Subcomponent • Dagger Android - “Befriend the Beast”

Slide 8

Slide 8 text

Who? Assumption : Basic familiarity with Dagger

Slide 9

Slide 9 text

SCOPES “FACE OF THE DAHAKA”

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

@ragdroid #chicagoroboto @SINGLETON EXAMPLE

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

@ragdroid #chicagoroboto CASE 1 DEPENDENCY WITH SCOPE

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 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 19

Slide 19 text

Provider 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 20

Slide 20 text

Provider • For each @Provides annotation dagger generates a Provider * • Dagger’s Factory interface is also a Provider • Dagger has various implementations of Providers: • SingleCheck • DoubleCheck (javax.inject) * Not for unscoped dependencies - Coming up

Slide 21

Slide 21 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 22

Slide 22 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 23

Slide 23 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 24

Slide 24 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 25

Slide 25 text

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

Slide 26

Slide 26 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 27

Slide 27 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 28

Slide 28 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 29

Slide 29 text

@ragdroid #chicagoroboto CASE 2 DEPENDENCY W/O SCOPE

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

@ragdroid #chicagoroboto CASE 3 @REUSABLE

Slide 40

Slide 40 text

@Reusable • Limit the instantiation. • Use when Exact same instance not needed. • Can Have multiple sub-components caching different instances.

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

SomeObject @Reusable class SomeObject @Inject constructor()

Slide 44

Slide 44 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 45

Slide 45 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 46

Slide 46 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 47

Slide 47 text

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

Slide 48

Slide 48 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 49

Slide 49 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 50

Slide 50 text

@Singleton vs @Reusable vs No Scope • Heavy mutable object with State : @Singleton • Heavy immutable object / stateless : @Reusable • Not Heavy : No Scope •

Slide 51

Slide 51 text

@ragdroid #chicagoroboto GOD APP MODULE

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

@ragdroid #chicagoroboto God App Module How To Improve?

Slide 57

Slide 57 text

@ragdroid #chicagoroboto God App Module Splitting App Module

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

@ragdroid #chicagoroboto Splitting App Module

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

@ragdroid #chicagoroboto Custom Scopes

Slide 64

Slide 64 text

@ragdroid #chicagoroboto Custom Scopes Multiple Components

Slide 65

Slide 65 text

Multiple Components 1. Dependent Components 2. Sub-Components

Slide 66

Slide 66 text

COMPONENT DEPENDENCIES

Slide 67

Slide 67 text

@ragdroid #chicagoroboto SUB COMPONENT VS DEPENDENT COMPONENT

Slide 68

Slide 68 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 Application

Slide 69

Slide 69 text

AppComponent @Singleton DaggerAppComponent LoginComponent Sub Component @ActivityScope Dependent Component DaggerUserComponent • dependency HomeComponent ItemsComponent @UserScope

Slide 70

Slide 70 text

@ragdroid #chicagoroboto APP COMPONENT

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

@ragdroid #chicagoroboto DAHAKA APPLICATION

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

DEPENDENT COMPONENTS

Slide 77

Slide 77 text

@ragdroid #chicagoroboto USER COMPONENT

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

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

Slide 80

Slide 80 text

@ragdroid #chicagoroboto USER MANAGER

Slide 81

Slide 81 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 82

Slide 82 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 83

Slide 83 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 84

Slide 84 text

@ragdroid #chicagoroboto DAGGER USER COMPONENT (Generated)

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

SUB COMPONENTS

Slide 88

Slide 88 text

@ragdroid #chicagoroboto LOGIN SUBCOMPONENT

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

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

Slide 91

Slide 91 text

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

Slide 92

Slide 92 text

@ragdroid #chicagoroboto DAGGER APP COMPONENT (Generated)

Slide 93

Slide 93 text

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

Slide 94

Slide 94 text

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

Slide 95

Slide 95 text

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

Slide 96

Slide 96 text

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

Slide 97

Slide 97 text

@ragdroid #chicagoroboto SUB COMPONENT VS DEPENDENT COMPONENT

Slide 98

Slide 98 text

<> AppComponent fun schedulerProvider() @Singleton

Slide 99

Slide 99 text

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

Slide 100

Slide 100 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 101

Slide 101 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 102

Slide 102 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 103

Slide 103 text

@ragdroid #chicagoroboto Custom Scope Advantages • Dependency Lifecycle Management • Modularized code

Slide 104

Slide 104 text

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

Slide 105

Slide 105 text

@ragdroid #chicagoroboto Some Limitations Dagger 2 Android

Slide 106

Slide 106 text

DAGGER 2 ANDROID “BEFRIEND THE BEAST”

Slide 107

Slide 107 text

@ragdroid #chicagoroboto DAHAKA APPLICATION

Slide 108

Slide 108 text

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

Slide 109

Slide 109 text

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

Slide 110

Slide 110 text

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

Slide 111

Slide 111 text

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

Slide 112

Slide 112 text

@ragdroid #chicagoroboto APP COMPONENT

Slide 113

Slide 113 text

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

Slide 114

Slide 114 text

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

Slide 115

Slide 115 text

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

Slide 116

Slide 116 text

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

Slide 117

Slide 117 text

@Module abstract class AppBindingModule { @ContributesAndroidInjector(modules = arrayOf(LoginModule::class)) @ActivityScope internal abstract fun loginActivity(): LoginActivity } AppBindingModule No need to create LoginActivitySubcomponent class in the above case. @ContributesAndroidInjector AppBindingModule

Slide 118

Slide 118 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 119

Slide 119 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 120

Slide 120 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 121

Slide 121 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 122

Slide 122 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 123

Slide 123 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 124

Slide 124 text

@ragdroid #chicagoroboto LOGIN ACTIVITY

Slide 125

Slide 125 text

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

Slide 126

Slide 126 text

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

Slide 127

Slide 127 text

AndroidInjection.inject(LoginActivity) AndroidInjection.inje

Slide 128

Slide 128 text

AndroidInjection.inject(LoginActivity) AndroidInjection.inje AndroidInjection

Slide 129

Slide 129 text

AndroidInjection.inject(LoginActivity) AndroidInjection.inje AndroidInjection DaggerAppComponent

Slide 130

Slide 130 text

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

Slide 131

Slide 131 text

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

Slide 132

Slide 132 text

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

Slide 133

Slide 133 text

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

Slide 134

Slide 134 text

public interface HasActivityInjector { AndroidInjector activityInjector(); } HasActivityInjector

Slide 135

Slide 135 text

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

Slide 136

Slide 136 text

HasActivityInjector <> HasActivityInjector fun activityInjector() : AndroidInjector

Slide 137

Slide 137 text

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

Slide 138

Slide 138 text

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

Slide 139

Slide 139 text

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

Slide 140

Slide 140 text

DispatchingAndroidInjector Provider LoginActivity.class Class Provider DispatchingAndroidInject • gets the Subcomponent.Builder from injectorFactory. • creates an instance using Builder. • calls component.inject(instance) to perform injections. • Injects members for Android types : Activity, Fragment, etc • Has a Map> injectorFactories.

Slide 141

Slide 141 text

AndroidInjection.inject(LoginActivity)

Slide 142

Slide 142 text

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

Slide 143

Slide 143 text

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

Slide 144

Slide 144 text

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

Slide 145

Slide 145 text

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

Slide 146

Slide 146 text

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

Slide 147

Slide 147 text

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

Slide 148

Slide 148 text

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

Slide 149

Slide 149 text

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

Slide 150

Slide 150 text

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

Slide 151

Slide 151 text

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

Slide 152

Slide 152 text

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

Slide 153

Slide 153 text

@ragdroid #chicagoroboto LOGIN ACTIVITY

Slide 154

Slide 154 text

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

Slide 155

Slide 155 text

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

Slide 156

Slide 156 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 • 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 157

Slide 157 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 158

Slide 158 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-kotlin : dagger-android with Dependent Component • subcomponent : UserComponent as subcomponent • dependent-component-kotlin : UserComponent as dependent component

Slide 159

Slide 159 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 160

Slide 160 text

@ragdroid #chicagoroboto CUT SCENES

Slide 161

Slide 161 text

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

Slide 162

Slide 162 text

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

Slide 163

Slide 163 text

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

Slide 164

Slide 164 text

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