Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Unconventional Android - Dependency Injection w...
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Richard Cirerol
March 18, 2017
Programming
110
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Unconventional Android - Dependency Injection with Dagger
Richard Cirerol
March 18, 2017
More Decks by Richard Cirerol
See All by Richard Cirerol
Introduction to Kotlin, Pt. 1
codeprogression
0
130
Android Studio Tips
codeprogression
0
110
Android: Testing Reactive MVP Applications
codeprogression
0
180
Unconventional Android v3
codeprogression
0
48
ReactiveX in Android
codeprogression
0
77
Unconventional Android v2
codeprogression
3
430
A Brief History of the Internet
codeprogression
1
500
Other Decks in Programming
See All in Programming
LoopHub - ローカルで動く GitHub で、AI と共同開発
jugyo
1
560
AI が書く Go コードの品質を劇的に向上させる Linter: “declscope”
mpyw
0
380
Heart of Swift Concurrency
koher
0
920
Webの地図
yosuke_furukawa
PRO
6
4.6k
What We Talk About When We Talk About XP
m_seki
2
660
巨大モノリシックアプリ モダン化大作戦
ktcryomm
1
1k
WebMCP Challenge に星空観察アプリで参加した話
okajun35
0
180
iOSDC Japan 2026 - Swiftで作って学ぼう!データベース自作入門
kaseken
2
170
The Good Stuff, Not the Slop: Engineering High-Quality Android Apps with Modern AI Tooling
danybony
1
260
スマートフォンでモールス信号を送受信する 〜スマートフォンのLEDとカメラで作る光通信の設計と実装〜
atsuki_seo
0
150
SONY CISC-NEWS NWS-1750 + NWB-225 フレームバッファの NetBSD/news68k ドライバ実装 / OSC2026Hiroshima
tsutsui
0
120
Snowflakeで業務アプリを作ろう。 Snowflakeのアプリ機能解説&実践ガイド
ayumu_yamaguchi
1
280
Featured
See All Featured
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
540
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.8k
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.8k
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
730
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
Building an army of robots
kneath
307
46k
Being A Developer After 40
akosma
91
590k
Testing 201, or: Great Expectations
jmmastey
46
8.3k
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
2
280
Mobile First: as difficult as doing things right
swwweet
225
10k
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
410
The Mindset for Success: Future Career Progression
greggifford
PRO
0
500
Transcript
Dependency Injection Unconventional Android Unconventional Android - Dependency Injection. ©2017
Richard Cirerol 1
Agenda 4 Introductions 4 What is Unconventional Android? 4 Dependency
Injection in Java and Android 4 Dagger 2 Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 2
Who am I? Unconventional Android - Dependency Injection. ©2017 Richard
Cirerol 3
Richard Cirerol @codeprogression Unconventional Android - Dependency Injection. ©2017 Richard
Cirerol 4
Richard Cirerol Android Core Team Lead BAMTech Unconventional Android -
Dependency Injection. ©2017 Richard Cirerol 5
Richard Cirerol Pluralsight Author Unconventional Android - Dependency Injection. ©2017
Richard Cirerol 6
Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 7
http://bit.ly/mlbam-theverge Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 8
What is Unconventional Android development? Unconventional Android - Dependency Injection.
©2017 Richard Cirerol 9
Android development that follows conventional software development practices. Unconventional Android
- Dependency Injection. ©2017 Richard Cirerol 10
Android development that follows conventional software development practices. Not (necessarily)
the Google sample way. Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 11
Android development that follows conventional software development practices. Not (necessarily)
the Google sample way. Therefore, unconventional. Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 12
Electronic Program Guide A schedule of events 4 Activity (View)
4 Presenter 4 Service (Model) Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 13
Activity class ScoreboardActivity: AppCompatActivity { override fun onCreate(saveInstanceState: Bundle){ val
eventService = Retrofit.Builder() //...build up service .build().create<EventService>() val schedule = api.getSchedule() setupRecyclerView(schedule) } } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 14
We'll just use MVP (Model-View-Presenter) to make things a little
cleaner... Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 15
Activity class ScoreboardActivity: AppCompatActivity { lateinit var presenter: ScoreboardPresenter; override
fun onCreate(saveInstanceState: Bundle){ val service = EventServiceBuilder.get() presenter = ScoreboardPresenter(service) } override fun onResume() { presenter.getSchedule().subscribe(subscriber) } } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 16
Presenter class ScoreboardPresenter(val service: EventService) { fun getSchedule(): Single<List<Event>> {
return service.getEvents(today) } } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 17
Service interface EventService { @GET fun getEvents(start: DateTime, end: DateTime?):
Single<List<Event>> @GET fun getEvent(id:Long): Single<Event> } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 18
High-coupling + Low-cohesion = Brittle software Unconventional Android - Dependency
Injection. ©2017 Richard Cirerol 19
Coupling1 The degree of interdependence between software modules. 1 https://en.wikipedia.org/wiki/Coupling_(computer_programming)
Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 20
Effects of High Coupling1 A change in one module usually
forces a ripple effect of changes in other modules. 1 https://en.wikipedia.org/wiki/Coupling_(computer_programming) Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 21
Cohesion2 4 the degree to which the elements of a
module belong together 2 https://en.wikipedia.org/wiki/Cohesion_(computer_science) Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 22
High Cohesion2 Traits: 4 robust 4 reliable 4 reusable 4
understandable 2 https://en.wikipedia.org/wiki/Cohesion_(computer_science) Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 23
Low Cohesion2 Traits: 4 difficult to maintain 4 difficult to
test 4 difficult to reuse 4 difficult to understand 2 https://en.wikipedia.org/wiki/Cohesion_(computer_science) Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 24
Problem #1 (reusability) EventService is probably shared Unconventional Android -
Dependency Injection. ©2017 Richard Cirerol 25
Activity class ScoreboardActivity: AppCompatActivity { override fun onCreate(saveInstanceState: Bundle){ val
service = EventServiceBuilder.get() presenter = ScoreboardPresenter(service) } } class GameActivity: AppCompatActivity { override fun onCreate(saveInstanceState: Bundle){ val service = EventServiceBuilder.get() presenter = GamePresenter(service) } } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 26
@Test fun testEventService(){ val service = EventServiceBuilder.get() // <- Why
is this bad? //... } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 27
Problem #2 (robustness) EventService may change Unconventional Android - Dependency
Injection. ©2017 Richard Cirerol 28
Activity class ScoreboardActivity: AppCompatActivity { override fun onCreate(saveInstanceState: Bundle){ val
service = EventServiceBuilder.get(BuildConfig.ENVIRONMENT) presenter = ScoreboardPresenter(service) } } class GameActivity: AppCompatActivity { override fun onCreate(saveInstanceState: Bundle){ val service = EventServiceBuilder.get(BuildConfig.ENVIRONMENT) presenter GamePresenter(service) } } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 29
Problem #3 (testability, reusability) The presenters are highly coupled to
EventService Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 30
Service class RestEventService : EventService { //... } class WebSocketEventService
: EventService { //... } class InMemoryEventService : EventService { //... class TestEventService : EventService { //... } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 31
Problem #4 (reliability, maintainability) The presenter may change its dependencies
Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 32
class ScoreboardPresenter( val eventService: EventService, val statsService: StatsService) { fun
getSchedule(): Single<List<Event>> { return service.getEvents(today) .combineWith(statsService.getStats()) } } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 33
// ScoreboardActivity val eventService = EventServiceBuilder.get() val statsService = StatsServiceBuilder.get()
presenter = ScoreboardPresenter(eventService, statsService) //... presenter.getSchedule().subscribe(subscriber) Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 34
That escalated quickly... Unconventional Android - Dependency Injection. ©2017 Richard
Cirerol 35
There is another way Unconventional Android - Dependency Injection. ©2017
Richard Cirerol 36
What is dependency injection? Unconventional Android - Dependency Injection. ©2017
Richard Cirerol 37
Inversion of Control 4 Reverses the creation of dependencies 4
Encourages: 4 High cohesion 4 Low coupling Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 38
Inversion of Control Two ways to invert dependencies... Service Locator
vs Dependency Injection3 3 https://martinfowler.com/articles/injection.html#ServiceLocatorVsDependencyInjection Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 39
Service Locator A class asks a locator for its dependencies.
Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 40
Service Locator class ScoreboardActivity: AppCompatActivity { lateinit var presenter: ScoreboardPresenter;
fun onCreate(saveInstanceState: Bundle) { presenter = ServiceLocator.get<ScoreboardPresenter>() } } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 41
Service Locator Singleton Registry: - Dependencies often stored in a
map - The ScoreboardPresenter will be provided by the ServiceLocator - The ScoreboardPresenter should have its dependencies provided before being returned by the ServiceLocator Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 42
Service Locator class ScoreboardActivity: AppCompatActivity { lateinit var presenter: ScoreboardPresenter;
lateinit var prefs: SharedPreferences; fun onCreate(saveInstanceState: Bundle) { presenter = ServiceLocator.get<ScoreboardPresenter>() prefs = ServiceLocator.get<SharedPreferences>() } } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 43
Dependency Injection A class is provided its dependencies. Unconventional Android
- Dependency Injection. ©2017 Richard Cirerol 44
Dependency Injection class ScoreboardActivity: AppCompatActivity { lateinit var presenter: ScoreboardPresenter;
@Inject set fun onCreate(saveInstanceState: Bundle) { val injector = ScheduleInjector.create() injector.inject(this) } } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 45
Dependency Injection class ScoreboardActivity: AppCompatActivity { lateinit var presenter: ScoreboardPresenter;
@Inject set lateinit var prefs: SharedPreferences; @Inject set fun onCreate(saveInstanceState: Bundle) { val injector = ScheduleInjector.create() injector.inject(this) } } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 46
Dependency Injection 4 The target class declares its dependencies with
the @Inject annotation 4 The injector builds a graph of the dependencies - often called an object graph or dependency graph. 4 The injector provides the target class with the fully constructed dependencies when inject(target) is called. Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 47
Dependency Injection in Java Unconventional Android - Dependency Injection. ©2017
Richard Cirerol 48
JSR-330 4 The change that promoted dependency injection in Java.
4 Released in October 2009. Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 49
JSR-330 We propose to maximize reusability, testability and maintainability of
Java code by standardizing an extensible dependency injection API. -- Google and SpringSource Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 50
JSR-330 4 @Inject: marks a requested dependency 4 @Scope: meta-annotation
for dependency lifecycle 4 @Singleton: application-wide @Scope 4 @Qualifier: meta-annotation for dependency differentiation 4 @Named: string-based @Qualifier 4 Provider<T> Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 51
@Inject Identifies injectable constructors, fields, and methods Unconventional Android -
Dependency Injection. ©2017 Richard Cirerol 52
Constructor Injection //java public class ScoreboardPresenter { private EventService service;
@Inject public ScoreboardPresenter(EventService service){ this.service = service; } } //kotlin class ScoreboardPresenter @Inject constructor(val service: EventService) Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 53
Constructor Injection 4 Preferred injection type 4 Always in a
valid state 4 All constructor dependencies must be available at creation Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 54
Field Injection //java public class ScoreboardActivity implements AppCompatActivity { @Inject
ScoreboardPresenter presenter; @Override public void onCreate(Bundle savedInstanceState) { Injector.inject(this); } } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 55
Field Injection //kotlin class ScoreboardActivity: AppCompatActivity() { lateinit var presenter:
ScoreboardPresenter @Inject set override fun onCreate(savedInstanceState: Bundle) { Injector.inject(this) } } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 56
Field Injection 4 Good for classes where you are not
responsible for construction 4 May be in invalid state after construction 4 Sometimes called Interface Injection Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 57
Method Injection //kotlin @Inject fun setDependency(presenter: Presenter) { this.presenter =
presenter } @Inject fun register(publisher: Publisher) { publisher.registerListener(this) } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 58
Method Injection 4 Similar to field injection, but allows for
side effects 4 If used to assign members, class may be in an invalid state 4 Also called Setter Injection Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 59
Dagger 2 A Dependency Injection Framework for Java and Android
Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 60
Dagger 2 Based on JSR-330 Unconventional Android - Dependency Injection.
©2017 Richard Cirerol 61
Dagger by Square Unconventional Android - Dependency Injection. ©2017 Richard
Cirerol 62
Dagger 2 by Google Unconventional Android - Dependency Injection. ©2017
Richard Cirerol 63
DAG-ger D irected A cyclic G raph Unconventional Android -
Dependency Injection. ©2017 Richard Cirerol 64
Directed Graph Unconventional Android - Dependency Injection. ©2017 Richard Cirerol
65
Undirected Graph Unconventional Android - Dependency Injection. ©2017 Richard Cirerol
66
Directed Acyclic Graph Unconventional Android - Dependency Injection. ©2017 Richard
Cirerol 67
Dagger 2 4 A DAG of dependencies 4 Does not
use reflection to get dependencies 4 Instead, generates the dependency graph at compile- time via annotation processing and code generation Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 68
Adding Dagger 2 to a Java-based Android Project // ./build.gradle
dependencies { // ... classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' } // ./app/build.gradle apply plugin: 'com.android.application' apply plugin: 'com.neenbedankt.android-apt' dependencies { compile "com.google.dagger:dagger:$daggerVersion" apt "com.google.dagger:dagger-compiler:$daggerVersion" } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 69
Adding Dagger 2 to a Kotlin-based Android Project // ./build.gradle
dependencies { // ... // add kotlin plugin classpath } // ./app/build.gradle apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' dependencies { // add kotlin stdlib compile "com.google.dagger:dagger:$daggerVersion" kapt "com.google.dagger:dagger-compiler:$daggerVersion" } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 70
Dagger 2 Annotations 4 @Module: (class, abstract class) marks a
dependency container 4 @Provides: (method) marks a constructed dependency 4 @Binds: (abstract method) marks a constructed dependency Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 71
Dagger 2 Annotations (continued) @Component: (interface) 4 uses modules (dependency
composition) 4 defines injection targets 4 defines provisioning methods 4 can depend on other components Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 72
Dagger 2 Annotations (continued) @Subcomponent: (interface) 4 uses modules (dependency
composition) 4 defines injection targets 4 created by parent component Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 73
Providing Dependencies There are two ways to provide dependencies in
Dagger: - Annotating Classes - Via a Module-annotated class Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 74
Annotated Classes @Singleton class RestEventService: EventService // Declares the class
as a dependency @Inject constructor() Dependencies annotated with @Singleton will always return the same instance. Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 75
Annotated Classes The @Scope annotation (from JSR-330) @Scope @Retention(AnnotationRetention.RUNTIME) annotation
class ActivityScope A meta-annotation to define a custom scope. Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 76
Annotated Classes Applying a custom scope @ActivityScope class ScoreboardPresenter @Inject
constructor(val service: EventService) Classes annotated with a custom scope are "singletons" within the scope. Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 77
Annotated Classes Transient Scope class ScoreboardItemPresenter @Inject constructor() Classes not
annotated with a scope return a new instance for each call. Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 78
Dagger Modules 4 Provide constructed dependencies 4 Can be composed
(include other modules) Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 79
@Module(includes = arrayOf(PreferencesModule::class)) class ApplicationModule @Module class PreferencesModule(private val context:Context)
{ @Provides @Singleton fun sharedPreferences(): SharedPreferences { return PreferenceManager.getDefaultSharedPreferences(context) } } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 80
Module @Provides Marks a module method for binding by the
compiler. Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 81
Module Modules cannot mix scopes 4 All scope annotations must
match 4 Methods with no scope are allowed Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 82
@Module class ScoreboardActivityModule { @Provides fun dependency1(): Dependency1 { return
Dependency1.get() } @ActivityScope @Provides fun dependency2(): Dependency2 { return Dependency2.get() } // !!! Cannot mix scopes in a module @Singleton @Provides fun dependency3(): Dependency3 { return Dependency3.get() } } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 83
Modules Binding interfaces Unconventional Android - Dependency Injection. ©2017 Richard
Cirerol 84
Binding Interfaces The interface... interface PersistentStore { fun save(key: String,
data: String) fun load(key: String) : String? fun delete(key: String) } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 85
Binding Interfaces An implementation... @Singleton class DefaultPersistentStore @Inject constructor(val prefs:SharedPreferences)
: PersistentStore { override fun save(key: String, data: String) { prefs.edit().putString(key, data).commit() } override fun load(key: String): String? { return prefs.getString(key, null) } override fun delete(key: String) { prefs.edit().remove(key).commit() } } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 86
Binding Interfaces Don't do this... @Module(includes = arrayOf(PreferencesModule::class)) class ApplicationModule
{ @Provides @Singleton fun storage(prefs: SharedPreferences): PersistentStore { return DefaultPersistentStore(prefs) } } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 87
Binding Interfaces For interface dependencies: 4 Use an abstract class
4 Use @Binds instead of @Provides Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 88
Binding Interfaces @Module(includes = arrayOf(PreferencesModule::class)) abstract class ApplicationModule { @Binds
@Singleton abstract fun storage(store: DefaultPersistentStore): PersistentStore @Binds @Singleton @Named("REST") abstract fun restEventService(service: RestEventService): EventService @Binds @Singleton @Named("WS") abstract fun wsEventService(service: WsEventService): EventService } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 89
Module Rules 4 Only include dependencies that must be configured,
created, or built 4 Do not mix scopes in modules 4 Use an abstract class with @Binds to define the interface/implementation couplets Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 90
Dagger Components Unconventional Android - Dependency Injection. ©2017 Richard Cirerol
91
Component An annotated interface that defines injection targets. Unconventional Android
- Dependency Injection. ©2017 Richard Cirerol 92
Component @Singleton @Component(modules = arrayOf(ApplicationModule::class)) interface ApplicationComponent { // Members
injection fun inject(application: MobileApplication) } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 93
Component A scoped @Component means dependencies must: 4 Be annotated
with the same scope annotation, or... 4 Be transient (no scope annotation) Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 94
Component 4 Concrete implementation created at compile time 4 The
generated class is prefixed with Dagger 4 The concrete component is configured via a builder 4 Each declared (and nested) module is configured via the builder Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 95
class MobileApplication: Application() { @set:Inject lateinit var storage: PersistentStore @set:Inject
lateinit var prefs: SharedPreferences companion object { lateinit internal var component: ApplicationComponent } override fun onCreate(){ component = DaggerApplicationComponent.builder() //.applicationModule(ApplicationModule()) .preferencesModule(PreferencesModule(this)) .build() component.inject(this) } } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 96
Component component.inject(this) Assigns all the target's dependencies from the "directed
acyclic graph". Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 97
Component An annotated interface that: 4 Defines injection targets 4
Provisions methods to other components Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 98
Provisioned Dependencies (Exports) @Singleton @Component(modules = arrayOf(ApplicationModule::class)) interface ApplicationComponent{ //
Members injection fun inject(application: MobileApplication) // Provisioning methods (exports) // Exposes dependencies to other components fun prefs(): SharedPreferences } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 99
class ScoreboardActivity: AppCompatActivity() { @set:Inject lateinit var presenter: ScoreboardPresenter @set:Inject
lateinit var prefs: SharedPreferences var component: ScoreboardActivityComponent? = null override fun onCreate(savedInstanceState: Bundle) { component = DaggerScoreboardActivityComponent.builder() .applicationComponent(MobileApplication.component) .build() component?.inject(this) } override fun onDestroy() { component = null } } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 100
Component A Component can depend on other components. @ActivityScope @Component(dependencies=arrayOf(ApplicationComponent::class))
interface ScoreboardActivityComponent { fun inject(activity: ScoreboardActivity) } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 101
Provisioning Method A Component can expose dependencies to other components.
// interface ApplicationComponent fun prefs(): SharedPreferences Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 102
//class ScoreboardActivity @set:Inject lateinit var presenter: ScoreboardPresenter @set:Inject lateinit var
prefs: SharedPreferences Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 103
class ScoreboardPresenter @Inject constructor(val service: EventService) EventService is annotated with
@Singleton in the ApplicationModule. Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 104
//interface ApplicationComponent fun prefs(): SharedPreferences fun eventService(): EventService Unconventional Android
- Dependency Injection. ©2017 Richard Cirerol 105
Dagger 2 Component Inheritance 4 Via @Component annotation parameter 4
@Subcomponent Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 106
Component Inheritance @ActivityScope @Component(dependencies = arrayOf(ApplicationComponent.class), modules = arrayOf(ScoreboardActivityModule.class) interface
ScoreboardActivityComponent { fun inject(activity: ScoreboardActivity) } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 107
Subcomponent Inheritance @ActivityScope @Subcomponent(modules = arrayOf(ScoreboardActivityModule.class) interface ScoreboardActivitySubcomponent { fun
inject(activity: ScoreboardActivity) } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 108
Subcomponent Inheritance @Singleton @Component(modules = arrayOf(ApplicationModule.class)) interface ScoreboardActivityComponent { fun
inject(application: MobileApplication) fun scoreboardSubcomponent(module: ScoreboardActivityModule) : ScoreboardActivitySubcomponent } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 109
// ScoreboardActivity fun onCreate(savedInstanceState: Bundle) { val subcomponent = MobileApplication.component()
.scoreboardSubcomponent(ScoreboardActivityModule(this)) subcomponent.inject(this) } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 110
// ScoreboardActivity @Inject lateinit var presenter: ScoreboardPresenter @Inject lateinit var
prefs: SharedPreferences fun onCreate(savedInstanceState: Bundle) { val subcomponent = MobileApplication.component() .scoreboardSubcomponent() // <- service locator subcomponent.inject(this) // <- dependency injection } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 111
Interesting Uses for Subcomponent Activities with common - Views -
Behaviors Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 112
@ActivityScope @Subcomponent interface CommonSubcomponent { fun inject(eventsView: EventsView) fun inject(eventItemView:
EventItemView) } interface CommonInjector { fun getCommonSubcomponent(): CommonSubcomponent } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 113
@ActivityScope @Component(dependencies = arrayOf(MobileComponent::class)) interface ScoreboardActivityComponent : CommonInjector @ActivityScope @Component(dependencies
= arrayOf(MobileComponent::class)) interface SearchActivityComponent : CommonInjector Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 114
class ScoreboardActivity : AppCompatActivity, CommonInjector { override fun onCreate(savedInstanceState: Bundle)
{ component = ScoreboardActivityComponent.create() } override fun getCommonSubcomponent(): CommonSubcomponent { return component.getCommonSubcomponent() } } // repeat for SearchActivity (Base class?) Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 115
// class EventItemView : RelativeLayout @Inject lateinit var presenter: EventItemPresenter
override fun onViewAttachedToWindow(){ (context as CommonInjector).getCommonSubcomponent().inject(this) } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 116
// class EventItemView : RelativeLayout @Inject lateinit var presenter: EventItemPresenter
@Inject lateinit var eventsPresenter: EventsPresenter override fun onViewAttachedToWindow(){ (context as CommonInjector).getCommonSubcomponent().inject(this) } Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 117
This is just scratching the surface. Unconventional Android - Dependency
Injection. ©2017 Richard Cirerol 118
Review 4 Dependency Injection 4 Service Locator 4 JSR-330 annotations
4 Dagger 2 annotations 4 Using Dagger 2 in Android Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 119
Thanks! Richard Cirerol @codeprogression We're hiring! Android Engineer, Client Team
(http://grnh.se/imfhs71) Android Engineer, Core Team (http://grnh.se/617dof1) Unconventional Android - Dependency Injection. ©2017 Richard Cirerol 120