Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Unconventional Android - Dependency Injection w...
Search
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
120
Android Studio Tips
codeprogression
0
100
Android: Testing Reactive MVP Applications
codeprogression
0
170
Unconventional Android v3
codeprogression
0
42
ReactiveX in Android
codeprogression
0
66
Unconventional Android v2
codeprogression
3
420
A Brief History of the Internet
codeprogression
1
500
Other Decks in Programming
See All in Programming
並列実装の現場、2ヶ月間実務でAIを使い倒したAIもPCも私も限界が近い
ming_ayami
0
130
エージェンティックRAGにAWSで入門しよう!
har1101
9
1.7k
エンジニアと一緒にテストコードの設計と実装を改善した話
mototakatsu
0
210
LLMによるContent Moderationの本番運用の裏側と品質担保への挑戦
suikabar
3
730
PHPで使える日時の表現と、その知り方 #frontend_phpcon_do
o0h
PRO
0
260
正しくソフトウェアを作る、前提を疑うための認知の視点 / doubt-premise
minodriven
21
7k
AIを活用したE2Eテスト実装効率化のあゆみ / ebisu-mobile-14-kotetu
kotetuco
0
130
JavaDoc 再入門
nagise
1
380
Creating Composable Callables in Contemporary C++
rollbear
0
160
トークンをケチるな、設計しろ:GitHub Copilotを賢く使うコンテキスト戦略
ochtum
0
140
Even G2とAWSで推しのエージェントを召喚しよう!
har1101
1
120
Java × distroless で 軽量なコンテナイメージを / Java on Distroless
contour_gara
0
560
Featured
See All Featured
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.5k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
180
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
150
Google's AI Overviews - The New Search
badams
0
1k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
Information Architects: The Missing Link in Design Systems
soysaucechin
0
980
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
740
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.1k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.3k
Code Review Best Practice
trishagee
74
20k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
400
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