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