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
Dagger just got better
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Dino Bikić
October 04, 2017
Programming
50
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Dagger just got better
New features in the latest Dagger dependency injection library.
Dino Bikić
October 04, 2017
More Decks by Dino Bikić
See All by Dino Bikić
Razvoj Android aplikacija
biki
0
44
Other Decks in Programming
See All in Programming
最近”作らせてる” ローカルAIアプリの話
akit37
0
470
[2026-09-26]空論ジェネリックプロセス~テスト資産とAIで紡ぐ、再現可能なパフォーマンスチューニングの話~
tosite
0
270
The Rails Doctrine Decade
koic
2
590
UPDATE をやめる — EF Core でマスタをバージョン管理する
panda728
PRO
0
1.2k
【加筆修正版】Laravel のアプリケーションをどこにデプロイするか #phpcon_ehime
akase244
0
150
Compiling a real-world CLI tool to native with Static Hermes
tmikov2023
0
120
Agentic Software Factoryに、すごく賢いIF文を。 / super smart IF statement into the Agentic Software Factory.
rkaga
8
2.2k
作れる、でも消せるか?──安全に「枯らして消す」機能削除術 / Drain, Then Delete
chobishiba
2
690
GemmaをJevのように使ってみる / Use Gemma like Jev
kishida
5
790
AmebaブログはKMPから卒業します
kmars0605
0
190
全ての永続トークンを、生まれる前に消し去りたい!
sylph01
2
920
Agents on Rails - Rails at Scale 2026
irinanazarova
0
560
Featured
See All Featured
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
2
2.2k
brightonSEO & MeasureFest 2025 - Winning Strategies for Black Friday CRO & PPC - Christian Goodrich
cargoodrich
3
870
ラッコキーワード サービス紹介資料
rakko
1
5.3M
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
300
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
630
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
500
RailsConf 2023
tenderlove
30
1.6k
Become a Pro
speakerdeck
PRO
31
6.3k
It's Worth the Effort
3n
188
29k
What's in a price? How to price your products and services
michaelherold
247
13k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
Transcript
Dagger just got better DINO BIKIĆ
DAGGER
None
“Dagger is a fully static, compile-time dependency injection framework for
both Java and Android.”
“Dagger is a fully static, compile-time dependency injection framework for
both Java and Android.”
WHAT’S DEPENDENCY INJECTON?
BestActivityEver.java
BestActivityEver.java
BestActivityEver.java
BestActivityEver.java
BestActivityEver.java BestObjectEver.java
BestActivityEver.java BestObjectEver.java
BestActivityEver.java BestObjectEver.java EvenBetterObject.java GodObject.java MasterObject.java
HOW IT’S DONE?
dependencies { compile 'com.google.dagger:dagger-android:2.x' compile 'com.google.dagger:dagger-android-support:2.x' annotationProcessor 'com.google.dagger:dagger-android-processor:2.x' }
public class BestActivityEver extends Activity { @Inject BestObjectEver bestObjectEver; }
@Provides BestObjectEver bestObjectEver() { return new BestObjectEver(); }
@Module public class BestModule { @Provides BestObjectEver bestObjectEver() { return
new BestObjectEver(); } }
@Module public class BestModule { @Provides BestObjectEver bestObjectEver() { return
new BestObjectEver(); } @Provides MasterObject masterObject() { return new MasterObject(); } @Provides GodObject godObject() { return new GodObject(); } }
@Component(modules = BestModule.class) interface BestComponent { }
@Component(modules = BestModule.class) interface BestComponent { BestClassEver instantiate(); }
public class BestAppEver extends Application { static BestComponent bestComponent; }
public class BestAppEver extends Application { static BestComponent bestComponent; public
void onCreate() { super.onCreate(); } }
public class BestAppEver extends Application { static BestComponent bestComponent; public
void onCreate() { super.onCreate(); bestComponent = DaggerBestComponentEver.create(); } }
public class BestActivityEver extends Activity { @Inject BestObjectEver bestObjectEver; }
public class BestActivityEver extends Activity { @Inject BestObjectEver bestObjectEver; public
void onCreate() { super.onCreate(); BestAppEve.bestComponent } }
public class BestActivityEver extends Activity { @Inject BestObjectEver bestObjectEver; public
void onCreate() { super.onCreate(); BestAppEve.bestComponent.instantiate() } }
public class BestActivityEver extends Activity { @Inject BestObjectEver bestObjectEver; public
void onCreate() { super.onCreate(); BestAppEve.bestComponent.instantiate() .inject(BestActivityEver.this); } }
01 WHY IS DAGGER BEING USED?
1 functionality = 1 implementation
Unit tests
Code generation
02 DAGGER FUNCTIONALITIES
01 SINGLETONS
@Module public class MoshiModule { @Provides public Moshi converter() {
return MoshiUtils.moshi(); } }
@Module public class MoshiModule { @Provides @Singleton public Moshi converter()
{ return MoshiUtils.moshi(); } }
02 SCOPES
None
03 SUBCOMPONENTS
“ Components that inherit and extend the object graph of
a parent component.”
03 QUALIFIERS
@Module public class SchedulersModule { @Provides public Scheduler main() {
return AndroidSchedulers.mainThread(); } @Provides public Scheduler io() { return Schedulers.io(); } }
@Module public class SchedulersModule { @Provides @MainThread public Scheduler main()
{ return AndroidSchedulers.mainThread(); } @Provides @Io public Scheduler io() { return Schedulers.io(); } }
03 NEW FUNCTIONALITIES
01 NEW ANDROID INJECTOR
App component
@Component(modules = {}) public interface AppComponent { }
@Component(modules = { AndroidInjectionModule.class }) public interface AppComponent { }
@Component(modules = { AndroidInjectionModule.class, AppModule.class }) public interface AppComponent {
}
@Component(modules = { AndroidInjectionModule.class, AppModule.class, ActivityBuilder.class}) public interface AppComponent {
}
@Component(modules = { AndroidInjectionModule.class, AppModule.class, ActivityBuilder.class}) public interface AppComponent {
@Component.Builder interface Builder { } }
@Component(modules = { AndroidInjectionModule.class, AppModule.class, ActivityBuilder.class}) public interface AppComponent {
@Component.Builder interface Builder { @BindsInstance Builder application(Application application); } }
@Component(modules = { AndroidInjectionModule.class, AppModule.class, ActivityBuilder.class}) public interface AppComponent {
@Component.Builder interface Builder { @BindsInstance Builder application(Application application); AppComponent build(); } }
@Component(modules = { AndroidInjectionModule.class, AppModule.class, ActivityBuilder.class}) public interface AppComponent {
@Component.Builder interface Builder { @BindsInstance Builder application(Application application); AppComponent build(); } void inject(AndroidSampleApp app); }
DaggerAppComponent .builder() .application(this) .build() .inject(this);
Activity builder
@Module public abstract class ActivityBuilder { }
@Module public abstract class ActivityBuilder { abstract AndroidInjector.Factory<? extends Activity>
bindMainActivity(MainActivityComponent.Builder builder); }
@Module public abstract class ActivityBuilder { @Binds @IntoMap @ActivityKey(MainActivity.class) abstract
AndroidInjector.Factory<? extends Activity> bindMainActivity(MainActivityComponent.Builder builder); }
@Module public abstract class ActivityBuilder { @Binds @IntoMap @ActivityKey(MainActivity.class) abstract
AndroidInjector.Factory<? extends Activity> bindMainActivity(MainActivityComponent.Builder builder); @Binds @IntoMap @ActivityKey(DetailActivity.class) abstract AndroidInjector.Factory<? extends Activity> bindDetailActivity(DetailActivityComponent.Builder builder); }
App module
@Module(subcomponents = { MainActivityComponent.class, DetailActivityComponent.class}) public class AppModule { }
@Module(subcomponents = { MainActivityComponent.class, DetailActivityComponent.class}) public class AppModule { @Provides
@Singleton Context provideContext(Application application) { return application; } }
Activity component
@Subcomponent(modules = MainActivityModule.class) public interface MainActivityComponent extends AndroidInjector<MainActivity> }
@Subcomponent(modules = MainActivityModule.class) public interface MainActivityComponent extends AndroidInjector<MainActivity> @Subcomponent.Builder abstract
class Builder extends AndroidInjector.Builder<MainActivity>{} }
Activity module
@Module public class MainActivityModule { }
@Module public class MainActivityModule { @Provides MainView provideMainView(MainActivity mainActivity){ return
mainActivity; } }
@Module public class MainActivityModule { @Provides MainView provideMainView(MainActivity mainActivity){ return
mainActivity; } @Provides MainPresenter provideMainPresenter(MainView mainView, ApiService apiService){ return new MainPresenterImpl(mainView, apiService); } }
Application class
public class AndroidSampleApp extends Application implements HasActivityInjector { }
public class AndroidSampleApp extends Application implements HasActivityInjector { @Inject DispatchingAndroidInjector<Activity>
activityDispatchingAndroidInjector; }
public class AndroidSampleApp extends Application implements HasActivityInjector { @Inject DispatchingAndroidInjector<Activity>
activityDispatchingAndroidInjector; @Override public DispatchingAndroidInjector<Activity> activityInjector() { return activityDispatchingAndroidInjector; } }
Activity module
public class MainActivity extends Activity { }
public class MainActivity extends Activity { @Override protected void onCreate(Bundle
savedInstanceState) { AndroidInjection.inject(this); super.onCreate(savedInstanceState); } }
02 PRODUCERS
None
“The whole initialization process can be executed on background thread(s)
and delivered later to app’s main thread”
@Module @Provide @Component
@ProducerModule @Produces @ProductionComponent
@ProducerModule public class ApiProducerModule { @Produces public UserManager produceUserManager(ApiService
apiService) { return new UserManager(apiService); } }
@ProductionComponent( dependencies = AppComponent.class, modules = ApiProducerModule.class ) public
interface AppProductionComponent { }
@ProductionComponent( dependencies = AppComponent.class, modules = ApiProducerModule.class ) public
interface AppProductionComponent { ListenableFuture<UserManager> userManager(); ListenableFuture<UserModule.Factory> userModuleFactory(); }
AppProductionComponent appProductionComponent = DaggerAppProductionComponent.builder()
AppProductionComponent appProductionComponent = DaggerAppProductionComponent.builder() .executor(Executors.newSingleThreadExecutor())
AppProductionComponent appProductionComponent = DaggerAppProductionComponent.builder() .executor(Executors.newSingleThreadExecutor()) .appComponent(appComponent)
AppProductionComponent appProductionComponent = DaggerAppProductionComponent.builder() .executor(Executors.newSingleThreadExecutor()) .appComponent(appComponent) .build();
appProductionComponent = splashActivity.getAppProductionComponent();
appProductionComponent = splashActivity.getAppProductionComponent(); Futures.addCallback(appProductionComponent.userManager(), new FutureCallback<UserManager>() { @Override public void
onSuccess(UserManager result) { SplashActivityPresenter.this.userManager = result; } @Override public void onFailure(Throwable t) { } });
• PRO • Background, baby! PRODUCERS
• PRO • Background, baby! • CONS • Guava →
15k methods • More complicated code PRODUCERS
Better Producer implementation
@Module public class AppModule { @Provides @Singleton Retrofit retrofit()
{ Retrofit retrofit = new Retrofit(); retrofit.init(); return retrofit; } }
@Module public class AppModule { @Provides @Singleton Retrofit provideHeavyExternalLibrary()
{ Retrofit retrofit = new Retrofit(); retrofit.init(); return retrofit; } @Provides @Singleton Observable<Retrofit> provideRetrofitObservable( final Lazy<Retrofit> retrofit) { return Observable.fromCallable(retrofit::get) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } }
public class MainActivity extends AppCompatActivity { }
public class MainActivity extends AppCompatActivity { @Inject Observable<Retrofit> retrofitObservable;
Retrofit retrofit; }
public class MainActivity extends AppCompatActivity { @Inject Observable< Retrofit
> retrofitObservable; Retrofit retrofit; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(); } }
public class MainActivity extends AppCompatActivity { @Inject Observable< Retrofit
> retrofitObservable; Retrofit retrofit; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(); retrofitObservable.subscribe( ); } }
public class MainActivity extends AppCompatActivity { @Inject Observable<Retrofit> retrofitObservable;
Retrofit retrofit; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(); retrofitObservable.subscribe( retrofit -> retrofit = retrofit, throwable -> {} ); } }
03 @SUBCOMPONENT.BUILDER
The old way
@Component(modules = {AppModule.class, UtilsModule.class}) @Singleton public interface AppComponent {
}
@Component(modules = {AppModule.class, UtilsModule.class}) @Singleton public interface AppComponent { FirstComponent
plus(FirstModule firstModule, SecondModule secondModule); }
@Component(modules = {AppModule.class, UtilsModule.class}) @Singleton public interface AppComponent { FirstComponent
plus(FirstModule firstModule, SecondModule secondModule); } @FirstScope @Subcomponent(modules = {FirstModule.class, SecondModule.class}) public interface FirstComponent { }
@Component(modules = {AppModule.class, UtilsModule.class}) @Singleton public interface AppComponent { FirstComponent
plus(FirstModule firstModule, SecondModule secondModule); } @FirstScope @Subcomponent(modules = {FirstModule.class, SecondModule.class}) public interface FirstComponent { void inject(MainActivity mainActivity); }
FirstComponent firstComponent = appComponent
FirstComponent firstComponent = appComponent.plus();
FirstComponent firstComponent = appComponent.plus( new FirstModule() );
FirstComponent firstComponent = appComponent.plus( new FirstModule(), new SecondModule() );
FirstComponent firstComponent = appComponent.plus( new FirstModule(), new SecondModule(), … ,
…, …, … );
With builder:
@Component(modules = {AppModule.class, UtilsModule.class}) @Singleton public interface AppComponent { FirstComponent.Builder
firstComponentBuilder(); }
@Component(modules = {AppModule.class, UtilsModule.class}) @Singleton public interface AppComponent { FirstComponent.Builder
firstComponentBuilder(); } @FirstScope @Subcomponent(modules = {FirstModule.class, SecondModule.class}) public interface FirstComponent { }
@Component(modules = {AppModule.class, UtilsModule.class}) @Singleton public interface AppComponent { FirstComponent.Builder
firstComponentBuilder(); } @FirstScope @Subcomponent(modules = {FirstModule.class, SecondModule.class}) public interface FirstComponent { @Subcomponent.Builder interface Builder { } void inject(MainActivity mainActivity); }
@Component(modules = {AppModule.class, UtilsModule.class}) @Singleton public interface AppComponent { FirstComponent.Builder
firstComponentBuilder(); } @FirstScope @Subcomponent(modules = {FirstModule.class, SecondModule.class}) public interface FirstComponent { @Subcomponent.Builder interface Builder { FirstComponent.Builder firstModule(FirstModule firstModule); } void inject(MainActivity mainActivity); }
@Component(modules = {AppModule.class, UtilsModule.class}) @Singleton public interface AppComponent { FirstComponent.Builder
firstComponentBuilder(); } @FirstScope @Subcomponent(modules = {FirstModule.class, SecondModule.class}) public interface FirstComponent { @Subcomponent.Builder interface Builder { FirstComponent.Builder firstModule(FirstModule firstModule); FirstComponent.Builder secondModule(SecondModule secondModule); } void inject(MainActivity mainActivity); }
@Component(modules = {AppModule.class, UtilsModule.class}) @Singleton public interface AppComponent { FirstComponent.Builder
firstComponentBuilder(); } @FirstScope @Subcomponent(modules = {FirstModule.class, SecondModule.class}) public interface FirstComponent { @Subcomponent.Builder interface Builder { FirstComponent.Builder firstModule(FirstModule firstModule); FirstComponent.Builder secondModule(SecondModule secondModule); FirstComponent build(); } void inject(MainActivity mainActivity); }
FirstComponent firstComponent = appComponent .firstComponentBuilder()
FirstComponent firstComponent = appComponent .firstComponentBuilder() .firstModule(new FirstModule())
FirstComponent firstComponent = appComponent .firstComponentBuilder() .firstModule(new FirstModule()) .secondModule(new SecondModule())
FirstComponent firstComponent = appComponent .firstComponentBuilder() .firstModule(new FirstModule()) .secondModule(new SecondModule()) .build();
04 STATIC
@Provides User currentUser(AuthManager authManager) { return authManager.currentUser(); }
@Provides User currentUser(AuthManager authManager) { return authManager.currentUser(); } @Provides
@Singleton User currentUser(AuthManager authManager) { return authManager.currentUser(); }
@Provides static User currentUser(AuthManager authManager) { return authManager.currentUser(); }
“calling a static method is 15–20% faster than non- static
counterpart”
05 MULTIBINDINGS
@Module public class TranslatorsModule { @Provides @Singleton public Translator
provideGoogleTranslator(){ return new GoogleTranslator(); } }
@Module public class TranslatorsModule { @Provides(type = Provides.Type.SET) @Singleton
public Translator provideGoogleTranslator(){ return new GoogleTranslator(); } }
@Module public class TranslatorsModule { @Provides(type = Provides.Type.SET) @Singleton
public Translator provideGoogleTranslator() { return new GoogleTranslator(); } ... @Provides(type = Provides.Type.SET) @Singleton public Translator provideLongmanTranslator() { return new LongmanTranslator(); } }
public class TranslatorActivity extends Activity { @Inject Set<Translator> translators;
}
MORE NEW FUNCTIONALITIES! • Releasable reference • @Binds • @BindsOptionalOf
• @BindsInstance
REFERENCES • https://android.jlelse.eu/dagger-2-part-i-basic-principles-graph- dependencies-scopes-3dfd032ccd82 • https://medium.com/@iammert/new-android-injector-with-dagger-2- part-1-8baa60152abe • https://proandroiddev.com/dagger-2-part-three-new- possibilities-3daff12f7ebf
• https://google.github.io/dagger/users-guide.html • https://stackoverflow.com/a/39154297
Visit infinum.co or find us on social networks: infinum.co infinumco
infinumco infinum Any questions?
[email protected]
@DINO_BIKIC