Download - Sword fighting with Dagger GDG-NYC Jan 2016
![Page 1: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/1.jpg)
Sword Fighting with DaggerMike Nakhimovich
Android Engineer NY Times
![Page 2: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/2.jpg)
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)
![Page 3: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/3.jpg)
Compile Time Annotation Processing (Fast)
Superpowers
Lazy
Singleton
Provider
Object Scoping (Application/Session/Activity)
Why Dagger?
![Page 4: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/4.jpg)
In the Olden Days...
![Page 5: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/5.jpg)
Old Waypublic 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);
}
![Page 6: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/6.jpg)
Externalize Object Creation
![Page 7: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/7.jpg)
@Provides
Gson provideGson() {
}
Create a Provider
return new GsonBuilder().create();
}
![Page 8: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/8.jpg)
ModulesA Module is a part of your application that provides
implementations.
@Module public class DataModule {
}
@Provides Gson provideGson() {
return gsonBuilder.create();}
![Page 9: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/9.jpg)
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);
}
![Page 10: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/10.jpg)
Provides not necessaryYou can also annotate constructors directly to register
public class RedditDAO {
@Inject
public RedditDAO(RedditApi api) {
super();
}
}
Provided by Module
![Page 11: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/11.jpg)
Consuming Dependencies
![Page 12: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/12.jpg)
ComponentsA 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);
}
![Page 13: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/13.jpg)
Register with ComponentActivities/Services/Views register with an instance of a
component
public RedditView(Context context) {
getComponent().inject(this);
}
![Page 14: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/14.jpg)
Injection Fun
Now you can inject any dependencies
managed by the component.
As a field As a Constructor Param
![Page 15: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/15.jpg)
Instantiating Dependencies Old WayRedditPresenter 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);
}
![Page 16: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/16.jpg)
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
![Page 17: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/17.jpg)
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
![Page 18: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/18.jpg)
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;
}
@Overridepublic RedditPresenter get() { RedditPresenter instance = new RedditPresenter();membersInjector.injectMembers(instance);return instance;
}
public static Factory<RedditPresenter> create(MembersInjector<RedditPresenter> membersInjector) { return new RedditPresenter_Factory(membersInjector);
}}
![Page 19: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/19.jpg)
Dependency ChainThe Presenter has its own dependency
public class RedditPresenter {
@Inject RedditDAO dao;
}
![Page 20: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/20.jpg)
Dependency ChainWhich has its own dependency
public class RedditDAO {
private final RedditApi api;
@Inject
public RedditDAO(RedditApi api) {
this.api = api;
}
![Page 21: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/21.jpg)
Dagger Eliminates “Passing Through” Constructor Arguments
![Page 22: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/22.jpg)
Old WayRedditPresenter 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);
}
![Page 23: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/23.jpg)
Dagger Eliminates “Passing Through” Constructor Arguments
Dagger Way:Inject ONLY the dependencies each
object needs
![Page 24: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/24.jpg)
Type of Injections
Dagger has a few types of injection:
Direct
Lazy
Provider
![Page 25: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/25.jpg)
Direct
When instance is created also create the
dependency.
public class RedditPresenter {
@Inject RedditDAO dao;
}
![Page 26: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/26.jpg)
Lazy
Do not instantiate until .get() is called.
public class RedditPresenter {
@Inject Lazy<RedditDAO> dao;
}
Useful to keep startup time down
![Page 27: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/27.jpg)
ProviderProvider<T> allows you to inject multiple
instances of same object by calling .get()
public class RedditPresenter {
@Inject Provider<RedditDAO>
dao;
}
![Page 28: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/28.jpg)
Singletons Old Waypublic 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? :-(
![Page 29: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/29.jpg)
Singletons Dagger Way
Define objects to be Singletons
@Singleton @Provides
Gson provideGson() {
return gsonBuilder.create();
}
![Page 30: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/30.jpg)
Singletons Dagger Way
Define objects to be Singletons
@Singleton
public class RedditDAO{
@Inject
public RedditDAO() {
}
![Page 31: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/31.jpg)
Singleton Management
@Singleton = Single instance per Component
@Singleton
@Component( modules = {DataModule.class})
public interface AppComponent {
void inject(RedditView a);
}
![Page 32: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/32.jpg)
Scopes
Singleton is a scope annotation
@Scope
@Documented
@Retention(RUNTIME)
public @interface Singleton {}
We can create custom scope annotations
![Page 33: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/33.jpg)
Subcomponent
Creating a Subcomponent with a scope
@Subcomponent(modules = {
ActivityModule.class})
@ActivityScope
public interface ActivityComponent
![Page 34: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/34.jpg)
Subcomponent
plussing your component into another
component will inherit all objects
![Page 35: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/35.jpg)
Injecting ActivitiesComponents 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();
}}
![Page 36: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/36.jpg)
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.
![Page 37: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/37.jpg)
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.
![Page 38: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/38.jpg)
Scopes cont’dScopes empower “activity singletons” that you
can share and not worry about reinstantiating
for each activity.
![Page 39: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/39.jpg)
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.
![Page 40: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/40.jpg)
Dagger lets us decompose our activities
![Page 41: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/41.jpg)
Dagger @ The New York TimesWe 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
![Page 42: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/42.jpg)
Dagger @ The New York TimesWe 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
![Page 43: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/43.jpg)
Sample Project
https://github.com/digitalbuddha/StoreDemo
![Page 44: Sword fighting with Dagger GDG-NYC Jan 2016](https://reader033.vdocuments.us/reader033/viewer/2022051123/5a6d351e7f8b9aec418b4f4d/html5/thumbnails/44.jpg)
Come work with me
http://developers.nytimes.com/careers