32
Dependency Injec+on on Android By Joan Puig Sanz

Dependency Injection on Android

Embed Size (px)

DESCRIPTION

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

Citation preview

Page 1: Dependency Injection on Android

Dependency  Injec+on  on  Android  

By  Joan  Puig  Sanz  

Page 2: Dependency Injection on Android

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  

Page 3: Dependency Injection on Android

//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  

Page 4: Dependency Injection on Android

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  

Page 5: Dependency Injection on Android

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  

Page 6: Dependency Injection on Android

SIMPLE  EXAMPLE  Factory  paPern  

5  

Page 7: Dependency Injection on Android

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  

Page 8: Dependency Injection on Android

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  

Page 9: Dependency Injection on Android

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  

Page 10: Dependency Injection on Android

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  

Page 11: Dependency Injection on Android

Implementa+on  drawbacks  

10  

•  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    

Page 12: Dependency Injection on Android

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;

@Injectpublic HotMachine(Heater heater){ this.heater = heater;}public void start(){ heater.on(); //Other stuff}

} !

11  

Page 13: Dependency Injection on Android

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  

Page 14: Dependency Injection on Android

ANDROID  AND  DEPENDENCY  INJECTION  

RoboGuice  and  Dagger  

13  

Page 15: Dependency Injection on Android

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  

Page 16: Dependency Injection on Android

Example  -­‐  KitKat  Machine  

•  Chocolate  •  Cookie  •  Machine  – Heater  – Mold  

Chocolate  

Cookie  

Machine  

Heater  

Mold  

The  source  code  can  be  found  here:  hEp://beyondar.com/di.html  

15  

Page 17: Dependency Injection on Android

Example  -­‐  KitKat  Machine:  Steps  

1.  Define  dependencies  2.  Create  modules  3.  Prepare  the  graph  4.  Inject  dependencies  

16  

Page 18: Dependency Injection on Android

Example  –  KitKat  Machine:  Dependencies  

Chocolate  

ChocolateWithMilk  

Cookie  

TastyCookie  

Heater  

ElectricHeater  

Mold  

KitKatMold  

17  

Page 19: Dependency Injection on Android

Example  –  KitKat  Machine:  Dependencies  

KitKatMachine  Heater  Mold  

Machine    

void makeKitKat(Chocolate, Cookie)  

18  

Page 20: Dependency Injection on Android

Example  –  KitKat  Machine:  Dependencies  

!public interface Cookie {

public void doWhatCookiesDo();}public class TastyCookie implements Cookie{

@Injectpublic TastyCookie(){ print("New cookie");}

public void doWhatCookiesDo(){ print("Yummie yummie”);}

} !

Cookie    

void doWhatCookiesDo()

TastyCookie  

19  

Page 21: Dependency Injection on Android

Example  –  KitKat  Machine:  Dependencies  

public interface Machine {public void makeKitKat(Chocolate chocolate, Cookie cookie);

} !

@Singletonpublic 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”); }

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”); }

RoboGuice   Dagger  

20  

Page 22: Dependency Injection on Android

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>{

@Overridepublic Chocolate get() { return new ChocolateWithMilk();}

}

Dagger  @Modulepublic 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  

Page 23: Dependency Injection on Android

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  

Page 24: Dependency Injection on Android

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  

Page 25: Dependency Injection on Android

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  

Page 26: Dependency Injection on Android

OTHER  STUFF  TO  INJECT  Inject  inject  inject…  

25  

Page 27: Dependency Injection on Android

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  

Page 28: Dependency Injection on Android

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  

Page 29: Dependency Injection on Android

SIDE  BY  SIDE  Go!  

28  

Page 30: Dependency Injection on Android

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  

Page 31: Dependency Injection on Android

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  

Page 32: Dependency Injection on Android

beyondar.com  

@joanpuigsanz  

/joanpuigsanz  

31