Advertisement

Anton Minashkin Dagger 2 light

Android developer at Stanfy
Aug. 1, 2015
Advertisement

More Related Content

Slideshows for you(20)

Advertisement

Anton Minashkin Dagger 2 light

  1. Dagger 2. Right way to do Dependency Injections by Anton Minashkin
  2. Usual JAVA code public class Payroll { ... public long getWithholding(long payInDollars) { ... return withholding; } public long getAfterTaxPay(Employee employee) { long basePay = EmployeeDatabase.getInstance() .getBasePay(employee); long withholding = getWithholding(basePay); return basePay - withholding; } }
  3. Usual JAVA code public class Payroll { ... public long getWithholding(long payInDollars) { ... return withholding; } public long getAfterTaxPay(Employee employee) { long basePay = EmployeeDatabase.getInstance() .getBasePay(employee); long withholding = getWithholding(basePay); return basePay - withholding; } }
  4. Usual JAVA code public class Payroll { ... public long getWithholding(long payInDollars) { ... return withholding; } public long getAfterTaxPay(Employee employee) { long basePay = new EmployeeDatabase() .getBasePay(employee); long withholding = getWithholding(basePay); return basePay - withholding; } }
  5. What is DI? In software engineering, dependency injection is a software design pattern that implements inversion of control for software libraries.
  6. What is DI?
  7. Say “Hi!” to DI public class Payroll { ... EmployeeDatabase mEmployeeDatabase; public Payroll(EmployeeDatabase employeeDatabase) { mEmployeeDatabase = employeeDatabase; } public long getWithholding(long payInDollars) { ... return withholding; } public long getAfterTaxPay(Employee employee) { long basePay = mEmployeeDatabase.getBasePay(employee); long withholding = getWithholding(basePay); return basePay - withholding; } }
  8. Say “Hi!” to DI public class Payroll { ... EmployeeDatabase mEmployeeDatabase; public Payroll(EmployeeDatabase employeeDatabase) { mEmployeeDatabase = employeeDatabase; } public long getWithholding(long payInDollars) { ... return withholding; } public long getAfterTaxPay(Employee employee) { long basePay = mEmployeeDatabase.getBasePay(employee); long withholding = getWithholding(basePay); return basePay - withholding; } }
  9. ...but! Was: new Payroll().getAfterTaxPay(employee); Now: new Payroll(EmployeeDatabase.getInstance()) .getAfterTaxPay(employee);
  10. ...but! Was: new Payroll().getAfterTaxPay(employee); Now: new Payroll(EmployeeDatabase.getInstance()) .getAfterTaxPay(employee);
  11. Java! To the rescue! JSR-330
  12. JSR-330 public class Payroll { ... @Inject public Payroll(EmployeeDatabase employeeDatabase) { mEmployeeDatabase = employeeDatabase; } ... } OR public class Payroll { ... @Inject EmployeeDatabase mEmployeeDatabase; ... }
  13. DI frameworks ● Google Guice ● Spring DI ● Java EE6 CDI ● Dagger ● etc.
  14. DI frameworks ● Google Guice ● Spring DI ● Java EE6 CDI ● Dagger ● etc.
  15. Dagger 2. History Developed by Square Adopted by Google (Dagger 2)
  16. Dagger 2. Main features ● Android friendly ● JSR-330 ● Compile-time DI validation ● Full stack code generation ● User mimic code ● Easy to debug & understand
  17. Dagger 2. API class Thermosiphon implements Pump { private final Heater heater; @Inject Thermosiphon(Heater heater) { this.heater = heater; } ... }
  18. Dagger 2. API class CoffeeMaker { @Inject Heater heater; @Inject Pump pump; ... }
  19. Dagger 2. API @Module class DripCoffeeModule { @Provides Heater provideHeater() { return new ElectricHeater(); } @Provides Pump providePump(Thermosiphon pump) { return pump; } }
  20. Dagger 2. API @Component(modules = DripCoffeeModule.class) interface CoffeeShop { CoffeeMaker maker(); }
  21. Dagger 2. API CoffeeShop coffeeShop = DaggerCoffeeShop.builder() .dripCoffeeModule(new DripCoffeeModule()) .build(); ... CoffeeShop coffeeShop = DaggerCoffeeShop.create();
  22. Dagger 2. API public class CoffeeApp { public static void main(String[] args) { CoffeeShop coffeeShop = DaggerCoffeeShop.create(); coffeeShop.maker().brew(); } }
  23. Dagger 2. Scope @Provides @Singleton Heater provideHeater() { return new ElectricHeater(); }
  24. Dagger 2. Lazy class GridingCoffeeMaker { @Inject Lazy<Grinder> lazyGrinder; public void brew() { while (needsGrinding()) { // Grinder created once on first call to .get() and cached. lazyGrinder.get().grind(); } } }
  25. Dagger 2. Provider Injection class BigCoffeeMaker { @Inject Provider<Filter> filterProvider; public void brew(int numberOfPots) { ... for (int p = 0; p < numberOfPots; p++) { maker.addFilter(filterProvider.get()); //new filter every time. maker.addCoffee(...); maker.percolate(); ... } } }
  26. Dagger 2. Qualifiers @Qualifier @Documented @Retention(RUNTIME) public @interface Named { String value() default ""; }
  27. Dagger 2. Qualifiers class ExpensiveCoffeeMaker { @Inject @Named("water") Heater waterHeater; @Inject @Named("hot plate") Heater hotPlateHeater; ... }
  28. Dagger 2. Qualifiers @Provides @Named("hot plate") Heater provideHotPlateHeater() { return new ElectricHeater(70); } @Provides @Named("water") Heater provideWaterHeater() { return new ElectricHeater(93); }
  29. Dagger 2. Compile-time validation @Module class DripCoffeeModule { @Provides Heater provideHeater(Executor executor) { return new CpuHeater(executor); } } ... [ERROR] COMPILATION ERROR : [ERROR] error: java.util.concurrent.Executor cannot be provided without an @Provides-annotated method.
  30. Dagger 2. Generated code @Override public DataManager get() { DataManager provided = module.provideDataManager(authApiProvider.get(), articleApiProvider.get(), commentsApiProvider.get()); if (provided == null) { throw new NullPointerException("Cannot return null from a non-@Nullable @Provides method"); } return provided; } public static Factory<DataManager> create(DataManagerModule module, Provider<AuthApi> authApiProvider, Provider<ArticleApi> articleApiProvider, Provider<CommentApi> commentApiProvider) { return new DataManagerModule_ProvideDataManagerFactory(module, authApiProvider, articleApiProvider, commentApiProvider); }
  31. Dagger 2. Debugging Here should be example of Guice stacktrace: VERY-VERY-BAD-STACKTRACE And here is Dagger stacktrace: Mmmm… What a lovely stacktrace!
  32. Dagger 2. What should I inject? ● Anything that has constructor parameters ● Anything that is out of local scope ● Infrastructure ● Anything that is shared between >1 objects ● Diferent obj-graphs for diferent flavors
  33. Dagger 2. Where should I inject? public class MyApp extends Application { @Override public void onCreate() { registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { ... @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { inject(activity); } ... }); }
  34. Dagger 2 Example
  35. Dagger 2 Questions?
  36. RTFM! http://google.github.io/dagger/ https://youtu.be/oK_XtfXPkqw anton.minashkin@outlook.com
Advertisement