Dependency Injection
with Dagger2
František Gažo



Android developer at

What is Dependency Injection?
You use it even without knowing

"Dependency injection is a software design pattern in which one or more dependencies are injected, or passed by reference, into a dependent object. This pattern separates the creation of object's dependencies from its own behaviour, which allows program designs to be loosely coupled and to follow the Inversion of Control and Single Responsibility principle."

Why?
-
reduce coupling
-
more flexible
-
easier to test
How?
-
DIY
-
Library

RoboGuice
Dagger
No longer supported since August 2016

Deprecated since September 2016

Dagger 2
-
DI framework for both Java and Android
-
fully static, compile-time
-
version 1 created by Square
-
maintained by Google



Setup
dependencies {
compile 'com.google.dagger:dagger:2.x'
annotationProcessor 'com.google.dagger:dagger-compiler:2.x'
}
API

3 main parts:
-
Target
-
Component
-
Module
MainActivity
AppComponent
AppModule
@Inject
@Component
@Module
@Provides
Let's code...

Qualifiers
@Qualifier
@Retention(RUNTIME)
public @interface UserName {
}
class UserInfoActivity extends Activity {
@Inject
@UserName
String mUserName;
}
- custom
- standard
class UserInfoActivity extends Activity {
@Inject
@Named("user-name")
String mUserName;
}
@Module
class UserModule {
@Provides
@Named("user-name")
String provideUserName() {...}
}
Scopes
- define dependency lifetime
- application
- user
- activity
- ...


Scopes

-
Dagger generates Component implementations
-
manage them yourself
- be prepared!
Scopes
@Scope
@Retention(RUNTIME)
public @interface UserScope {
}
@Singleton
@Component(modules = {
DataModule.class
})
interface AppComponent { ... }
- custom
- standard
@Module
class DataModule {
@Provides
@Singleton
DB provideDatabase() {...}
}
bind Component to the Scope
Module cannot provide in different Scopes
@UserScope
@Subcomponent(modules = {
UserModule.class
})
interface UserComponent { ... }
@Module
class UserModule {
//...
@Provides
@UserScope
USer provideUser() {...}
}
@Subcomponent
@Component
@?

Subcomponents
// parent
@Component(modules = ParentModule.class)
interface ParentComponent {
ChildComponent childComponent();
// ChildComponent childComponent(ChildModule m);
}
@Module
class ParentModule { ... }
// child
@Subcomponent(modules = ChildModule.class)
interface ChildComponent { ... }
@Module
class ChildModule { ... }
ParentComponent parent = DaggerParentComponent.create();
ChildComponent child = parent.childComponent();
//ChildComponent child = parent.childComponent(new ChildModule(...));
Subcomponents
// parent
@Component(modules = ParentModule.class)
interface ParentComponent {
// define all public dependencies from Modules
}
@Module
class ParentModule { ... }
// child
@Component(
dependencies = ParentComponent.class,
modules = ChildModule.class
)
interface ChildComponent {
}
@Module
class ChildModule { ... }
ParentComponent parent = DaggerParentComponent.create();
ChildComponent child = DaggerChildComponent.builder()
.parentComponent(parent)
//.childModule(new ChildModule(...))
.build();
Testing

"you don’t need to use Dagger in your test at all"
end-to-end testing
-
Override bindings by subclassing modules (don’t do this!)
-
Separate component configurations
- Use build flavors
More
Lazy injecting
Producers
...
Video about Dagger 2 (Jake Wharton)
Thank you

Dagger2
By František Gažo
Dagger2
- 990