• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Dependency Injection on Android
 

Dependency Injection on Android

on

  • 620 views

How to use Dependency Injection on Android using RoboGuice and Dagger. This presentation was shown at the DroidCon NL 2013

How to use Dependency Injection on Android using RoboGuice and Dagger. This presentation was shown at the DroidCon NL 2013

Statistics

Views

Total Views
620
Views on SlideShare
608
Embed Views
12

Actions

Likes
1
Downloads
9
Comments
0

2 Embeds 12

https://twitter.com 6
http://www.linkedin.com 6

Accessibility

Upload Details

Uploaded via as Adobe PDF

Usage Rights

CC Attribution License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Dependency Injection on Android Dependency Injection on Android Presentation Transcript

    • Dependency  Injec+on  on   Android   By  Joan  Puig  Sanz  
    • About  Joan  Puig  Sanz   •  Electrical  Engineer   •  So<ware/hardware  fan  :)   •  Open  Source  Projects:   –  ServDroid:  Simple  web  Server   –  BeyondAR  Framework:  Augmented  Reality  framework   beyondar.com   1  
    • //TODO:   1.  What  is  Dependency  Injec+on?   2.  Simple  Example:  Factory  PaPern   3.  Android  and  Dependency  Injec+on   –  KitKatMachine  example  with  RoboGuice  and   Dagger   –  Compare  RoboGuice  and  Dagger   4.  Conclusions   2  
    • What  is  Dependency  Injec+on?   “Dependency  injec+on  is  a  so<ware  design  paPern   that  allows  the  removal  of  hard-­‐coded  dependencies   and  makes  it  possible  to  change  them,  whether  at   run-­‐+me  or  compile-­‐+me”     Dependency  Injec+on  is  like  ordering  a  hawaiian   pizza  but  specifying  the  ingredients,  for  instance,   instead  of  ham  we  want    pepperoni.       3  
    • What  does  Dependency  Injec+on  do?   •  It  improves  the  code:  reusable,  modulable  and   testability   •  It  allows  the  developer  to  focus  on  the  code   that  adds  a  plus  value  to  the  app:   –  No  need  to  worry  about  Singletons,  Factories  and   others.   4  
    • Factory  paPern   SIMPLE  EXAMPLE   5  
    • The  Factory  PaPern   public interface Heater { public void on(); public void off(); public boolean isHot(); } public class ElectricHeater implements Heater { private boolean heating; public void on() { heating = true; } public void off() { heating = false; } public boolean isHot() { return heating; } }! Heater     void  on()   void  off()   boolean  isHot()   ElectricHeater   6  
    • The  Factory  PaPern  –  wri+ng  it   public class HeaterFactory { private HeaterFactory () {} private static Heater instance = new ElectricHeater(); public static Heater getInstance() { return instance; } public static void setInstance(Heater heater) { instance = heater; } } public class HotMachine{ public void start(){ heater = HeaterFactory.getInstance(); heater.on(); // Other stuff } }! 7  
    • The  Factory  PaPern  –  Unit  Test   public void testHeater(){ Heater previous = HeaterFactory.getInstance(); try{ Heater mock = new mockHeater(); HeaterFactory.setInstance(mock); HotMachine machine = new HotMachine(); machine.start(); assertTrue(mock.isHot()); }finally{ HeaterFactory.setInstance(previous); } } 8  
    • Implementa+on  drawbacks   •  For  every  dependency  we  make  we  need  to   write  the  same  code.   •  Our  test  had  to  pass  the  mock  to  the  factory   and  then  clean  up  a<erwards.   •  You  cannot  determine  if  HotMachine  depends   on  Heater  at  first  sight   •  It  could  be  difficult  to  reuse  HotMachine  in  a   different  context     9  
    • Implementa+on  drawbacks   •  For  every  dependency  we  make  we  need  to   write  the  same  code.   •  Our  test  had  to  pass  the  mock  to  the  factory   and  then  clean  up  a<erwards.   •  You  cannot  determine  if  Machine  depends  on   Heater  at  first  sight   •  It  could  be  difficult  to  reuse  Machine  in  a   different  context     10  
    • Factory  PaPern  with  DI   •  We  need  to  define  a  module  specifying  what  are  we  going  to  inject.   –  Heater  as  ElectricHeater   –  We  also  can  define  how.   public class HotMachine{ private final Heater heater; @Inject public HotMachine(Heater heater){ this.heater = heater; } public void start(){ heater.on(); //Other stuff } }! 11  
    • Factory  PaPern  with  DI  –  Unit  Tes+ng   ! public void testHeater(){ Heater mock= new mockHeater(); HotMachine machine = new HotMachine(mock); machine.start() assertTrue(mock.isHot()); }! 12  
    • RoboGuice  and  Dagger   ANDROID  AND  DEPENDENCY   INJECTION   13  
    • Android   •  We  can  create  one  ourselves…  but  it  is  not   needed  and  it  is  a  lot  of  work   •  The  best  ones  are  RoboGuice  and  Dagger   –  RoboGuice  does  injec+on  during  run+me   •  hPps://github.com/roboguice/roboguice   –  Dagger  Generates  code   •  hPps://github.com/square/dagger/   14  
    • Example  -­‐  KitKat  Machine   •  Chocolate   •  Cookie   •  Machine   Chocolate   Heater   Machine   –  Heater   –  Mold   Cookie   Mold   The  source  code  can  be  found  here:  hEp://beyondar.com/di.html   15  
    • Example  -­‐  KitKat  Machine:   Steps   1.  2.  3.  4.  Define  dependencies   Create  modules   Prepare  the  graph   Inject  dependencies   16  
    • Example  –  KitKat  Machine:   Dependencies   Chocolate   Cookie   Heater   Mold   ChocolateWithMilk   TastyCookie   ElectricHeater   KitKatMold   17  
    • Example  –  KitKat  Machine:   Dependencies   Machine     void makeKitKat(Chocolate, Cookie)   Mold   KitKatMachine   Heater   18  
    • Example  –  KitKat  Machine:   Dependencies   ! public interface Cookie { public void doWhatCookiesDo(); } public class TastyCookie implements Cookie{ @Inject public TastyCookie(){ print("New cookie"); } public void doWhatCookiesDo(){ print("Yummie yummie”); } }! Cookie     void doWhatCookiesDo() TastyCookie   19  
    • Example  –  KitKat  Machine:   Dependencies   public interface Machine { public void makeKitKat(Chocolate chocolate, Cookie cookie); }! RoboGuice   @Singleton public class KitKatMachine implements Machine{ private Mold mold; private Heater heater; @Inject public KitKatMachine(Mold mold, Heater heater) { this.mold = mold; this.heater = heater; } public void makeKitKat(Chocolate chocolate, Cookie cookie){ heater.on(); Chocolate meltedChocolate = heater.melt(chocolate); mold.putToghether(cookie, chocolate); print (”Kitkat ready”); } Dagger   public class KitKatMachine implements Machine{ private Mold mold; private Lazy<Heater> heater; @Inject public KitKatMachine(Mold mold, Lazy<Heater> heater) { this.mold = mold; this.heater = heater; } public void makeKitKat(Chocolate chocolate, Cookie cookie){ heater.get.on(); Chocolate meltedChocolate = heater.get().melt(chocolate); mold.putToghether(cookie, chocolate); print (”Kitkat ready”); } 20  
    • Example  -­‐  KitKat  Machine:   Modules   RoboGuice   public class kitkatModule extends AbstractModule { protected void configure(){ bind(Cookie.class). toProvider(CookieProvider.class); bind(Chocolate.class). toProvider(ChocolateProvider.class); bind(Machine.class). to(KitkatMachine.class) } } public class ChocolateProvider implements Provider<Chocolate>{ @Override public Chocolate get() { return new ChocolateWithMilk(); } } Dagger   @Module public class KitkatModule { @Provides public Chocolate provideChocolate() { return new ChocolateWithMilk(); } @Provides public Cookie provideCookie(){ return new TastyCookie(); } @Provides @Singleton public Machine } providesMachine(KitKatMachine machine){ return machine; } 21  
    • Example  -­‐  KitKat  Machine:   Preparing  the  Graph   RoboGuice   public class KitKatMachineApplication extends Application { public void onCreate() { super.onCreate(); RoboGuice.setBaseApplicationInjector (this, Stage.PRODUCTION, getModules()); } protected Module[] getModules() { List<Module> modules = new ArrayList<Module>(); modules.add( RoboGuice.newDefaultRoboModule(this)); modules.add(new IngredientsModule()); modules.add(new MachineModule()); return (Module[]) modules.toArray(new Module[modules.size()]); } } Dagger   public class KitKatMachineApplication extends Application{ private ObjectGraph graph; public void onCreate() { super.onCreate();a graph = ObjectGraph.create( getModules().toArray()); } protected List<Object> getModules() { ArrayList<Object> modules = new ArrayList<Object>(); modules.add(new AndroidModule(this)); modules.add(new IngredientsModule()); modules.add(new MachineModule()); return modules; } public void inject(Object object) { graph.inject(object); } public ObjectGraph getApplicationGraph() { return graph; } 22  
    • Example  -­‐  KitKat  Machine:   Injec+ng  dependencies   public class HomeFragment extends #########{ @Inject Provider<Chocolate> chocolate; @Inject Provider<Cookie> cookie; @Inject Machine machine; // With Dagger we can use Lazy<Machine> to create a lazy singleton onResume(){ super.onResume() machine.makeKitKat(chocolate.get(), cookie.get()); } } #########   •  RoboGuice:  RoboFragment   •  Dagger:  BaseFragment  (your  custom  BaseFragment)   23  
    • Example  -­‐  KitKat  Machine:   Injec+ng  dependencies  -­‐  Dagger   public class BaseFragment extends Fragment { public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // Perform injection so that when this call returns all // dependencies will be available for use. ((KitKatMachineApplication) getApplication()).inject(this); } }! •  The  same  goes  for  the  Ac+vity.   •  It  is  highly  customizable   –  For  Instance:  It  is  possible  to  personalize  the  modules  that  we  want  to   inject  into  the  Ac+vity  (crea+ng  a  derivate  graph)   24  
    • Inject  inject  inject…   OTHER  STUFF  TO  INJECT   25  
    • Injec+ng  other  stuff  -­‐  Qualifiers   •  It  is  also  possible  to  inject  Qualifiers:   -­‐  Module:     @Provides @Named("app_version") public String getAppVersionCode(Context context) { return String.valueOf(getPackageInfo(context).versionCode); }!   -­‐  InjecSng:   ! @Inject @Named("app_version") String version;! ! 26  
    • Injec+ng  other  stuff  -­‐  RoboGuice   •  With  RoboGuice  we  can  inject  views,   preferences,  fragments,  extras  and  resources:     @InjectView(R.id.myTextView) private TextView myTextView; @InjectResource(R.string.app_name) private String appName;! ! •  We  also  can  inject  Context,  Inflater,  Services   and  some  other  Android  Objects.   –  Check  out  DefaultRoboModule.java  for  more  informa+on   27  
    • Go!   SIDE  BY  SIDE   28  
    • Side  by  side   RoboGuice   •  Can  inject  dependencies  in   private  fields   •  Method  Injec+on  supported   •  Configure  Proguard  is  hard   (doable)   •  Ready  to  inject  a  lot  of   Android  stuff   •  It  uses  Guice  which  is  more   server  related   •  Very  cool  framework   Dagger   •  Method  Injec+on  not  supported…   for  now   •  Faster.  In  a  big  app  it  can  reduce   the  startup  +me  in  a  few  seconds   •  Configure  Proguard  is  a  pain  in   the  ass   •  If  you  want  to  inject  Android  stuff   you  need  to  write  the  code  to  do   it   •  It  forces  developers  to  write  a  bit   more  code   •  Remember  that  it  generates   code!   •  Very  cool  framework   29  
    • Conclusions   •  Dependency  injec+ons  allows  the  developer  to  spend   +me  on  the  important  parts   •  It  makes  the  applica+on  more  modular   •  It  helps  tes+ng  your  applica+on   •  It  makes  your  code  less  like  spagheq,  ravioli,  lasagna   and  other  Italian  foods   •  The  developer  needs  to  understand  the  DI  framework   •  Easier  to  implement  at  the  beginning  than  at  the  end   •  Very  cool  frameworks  :)   30  
    • beyondar.com   @joanpuigsanz   /joanpuigsanz   31