+ All Categories
Home > Technology > Dependency Injection on Android

Dependency Injection on Android

Date post: 17-May-2015
Category:
Upload: joan-puig-sanz
View: 1,509 times
Download: 1 times
Share this document with a friend
Description:
How to use Dependency Injection on Android using RoboGuice and Dagger. This presentation was shown at the DroidCon NL 2013
Popular Tags:
32
Dependency Injec+on on Android By Joan Puig Sanz
Transcript
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  


Recommended