2. What is Dagger?
Dagger offers an alternative way to instantiate
and manage your objects through
Dependency Injection
Dagger 2 open sourced by Google
Dagger 1 – Square
Guice – Google (Dagger v.0)
5. Old Way
public class RedditView {
private RedditPresenter presenter;
public RedditView(...) {
Gson gson = new GsonBuilder().create();
RedditApi redditApi = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.build().create(RedditApi.class);
RedditDAO redditDAO = new RedditDAO(redditApi);
presenter=new RedditPresenter(redditDAO);
}
8. Modules
A Module is a part of your application that provides
implementations.
@Module public class DataModule {
}
@Provides Gson provideGson() {
return gsonBuilder.create();}
9. Dependencies
@Provides methods can have their own dependencies
@Provides
RedditApi provideRedditApi(Gson gson) {
return new Retrofit.Builder()
.addConverterFactory(
GsonConverterFactory.create(gson))
.build().create(RedditApi.class);
}
10. Provides not necessary
You can also annotate constructors directly to register
public class RedditDAO {
@Inject
public RedditDAO(RedditApi api) {
super();
}
}
Provided by Module
12. Components
A component is a part of your application that consumes
functionality. Built from Module(s)
@Component( modules = {DataModule.class})
public interface AppComponent {
void inject(RedditView a);
}
14. Injection Fun
Now you can inject any dependencies
managed by the component.
As a field As a Constructor Param
15. Instantiating Dependencies Old Way
RedditPresenter presenter;
public RedditView(Context context) {
super(context);
Gson gson = new GsonBuilder().create();
RedditApi redditApi = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
.create(RedditApi.class);
RedditDAO redditDAO = new RedditDAO(redditApi);
presenter=new RedditPresenter(redditDAO);
}
16. Once RedditView registers itself with a component,
Dagger will satisfy all managed dependencies with
@Inject annotations
@Inject RedditPresenter presenter;
public RedditView(...) {
getComponent().inject(this);
}
Instantiating Dependencies Dagger Way
17. How does Dagger do it?
A static DaggerAppComponent.builder() call creates a Builder instance;
Builder creates an DaggerAppComponent instance;
DaggerAppComponent creates a RedditView_MembersInjector instance;
RedditView_MembersInjectorr uses RedditPresenter_Factory to
instantiate RedditPresenter and injects it into RedditView.
Just as fast as hand written code but with fewer errors
18. Generated Code
@Generated("dagger.internal.codegen.ComponentProcessor")
public final class RedditPresenter_Factory implements Factory<RedditPresenter> {
private final MembersInjector<RedditPresenter> membersInjector;
public RedditPresenter_Factory(MembersInjector<RedditPresenter> membersInjector) {
assert membersInjector != null;
this.membersInjector = membersInjector;
}
@Override
public RedditPresenter get() {
RedditPresenter instance = new RedditPresenter();
membersInjector.injectMembers(instance);
return instance;
}
public static Factory<RedditPresenter> create(MembersInjector<RedditPresenter> membersInjector) {
return new RedditPresenter_Factory(membersInjector);
}
}
20. Dependency Chain
Which has its own dependency
public class RedditDAO {
private final RedditApi api;
@Inject
public RedditDAO(RedditApi api) {
this.api = api;
}
22. Old Way
RedditPresenter presenter;
public RedditView(...) {
super(context);
Gson gson = new GsonBuilder().create();
RedditApi redditApi = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
.create(RedditApi.class);
RedditDAO redditDAO = new RedditDAO(redditApi);
presenter=new RedditPresenter(redditDAO);
}
23. Dagger Eliminates “Passing Through”
Constructor Arguments
Dagger Way:
Inject ONLY the dependencies each
object needs
25. Direct
When instance is created also create the
dependency.
public class RedditPresenter {
@Inject RedditDAO dao;
}
26. Lazy
Do not instantiate until .get() is called.
public class RedditPresenter {
@Inject Lazy<RedditDAO> dao;
}
Useful to keep startup time down
27. Provider
Provider<T> allows you to inject multiple
instances of same object by calling .get()
public class RedditPresenter {
@Inject Provider<RedditDAO>
dao;
}
28. Singletons Old Way
public class MainActivity extends Activity {
SharedPreferences pref;
Gson gson;
ServerAPI api;
onCreate(...) {
MyApp app = (MyApp)getContext().getApplicationContext();
pref = app.getSharedPreferences();
gson = app.getGson();
api = app.getApi();
Why is MYApp managing all singletons?
:-(
29. Singletons Dagger Way
Define objects to be Singletons
@Singleton @Provides
Gson provideGson() {
return gsonBuilder.create();
}
30. Singletons Dagger Way
Define objects to be Singletons
@Singleton
public class RedditDAO{
@Inject
public RedditDAO() {
}
31. Singleton Management
@Singleton = Single instance per Component
@Singleton
@Component( modules = {DataModule.class})
public interface AppComponent {
void inject(RedditView a);
}
32. Scopes
Singleton is a scope annotation
@Scope
@Documented
@Retention(RUNTIME)
public @interface Singleton {}
We can create custom scope annotations
33. Subcomponent
Creating a Subcomponent with a scope
@Subcomponent(modules = {
ActivityModule.class})
@ActivityScope
public interface ActivityComponent
35. Injecting Activities
Components scoped (recreated) with each activity allows us to do silly things
like injecting an activity into scoped objects:
@ScopeActivity
public class Toaster {
@Inject Activity activity;
private static void showToast() {
Toast.makeText(activity, message).show();
}}
36. Inject a Scoped Object
@Inject
SnackbarUtil snackbarUtil;
there’s no need to pass activity into presenter and then
into the SnackBarMaker
objects can independently satisfy their own
dependencies.
37. Scoped
If you try to inject something into an object with a
different scope, Dagger with give compilation error.
Scopes let objects “share” the same instance of anything in
the scope. ToolbarPresenters, IntentHolders etc.
38. Scopes cont’d
Scopes empower “activity singletons” that you
can share and not worry about reinstantiating
for each activity.
39. Dagger @ The New York Times
How we leveraged scope at The Times:
Inject activity intents into fragments 2 layers down
Create a toolbar presenter, each activity and its views get
access to the same presenter
Inject an alerthelper/snackbar util that can show alerts.
41. Dagger @ The New York Times
We can inject something that is being provided
by a module in library project.
A/B Module within A/B Project provides
injectable A/B manager
API project owns API module etc. Main Project
creates a component using all the modules
42. Dagger @ The New York Times
We can inject different implementations for
same interface spread across build variants
using a FlavorModule.
Amazon Flavor provides module with Amazon
Messaging
Google Flavor provides module with Google
Messaging