Successfully reported this slideshow.

Sword fighting with Dagger GDG-NYC Jan 2016

4

Share

Upcoming SlideShare
Open sourcing the store
Open sourcing the store
Loading in …3
×
1 of 44
1 of 44

More Related Content

Related Books

Free with a 14 day trial from Scribd

See all

Sword fighting with Dagger GDG-NYC Jan 2016

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

×