Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Android Apps with Dagger (SF Android Meetup, Ap...

Android Apps with Dagger (SF Android Meetup, April 2014)

An introduction to dependency injection, the Dagger library, and how to combine the two in your Android applications.

http://www.meetup.com/sfandroid/events/171955222/

Jake Wharton

April 22, 2014
Tweet

More Decks by Jake Wharton

Other Decks in Technology

Transcript

  1. Dependency Injection • Every single app has some form of

    dependency injection • Separate behavior of something from its required classes
  2. Dependency Injection • Every single app has some form of

    dependency injection • Separate behavior of something from its required classes Tweeter
  3. Dependency Injection • Every single app has some form of

    dependency injection • Separate behavior of something from its required classes Tweeter Twitter API
  4. Dependency Injection • Every single app has some form of

    dependency injection • Separate behavior of something from its required classes Tweeter Twitter API HTTP Client
  5. public  class  Tweeter  {      public  void  tweet(String  tweet)

     {          TwitterApi  api  =  new  TwitterApi();          api.postTweet("JakeWharton",  tweet);      }   }
  6. public  class  Tweeter  {      public  void  tweet(String  tweet)

     {          TwitterApi  api  =  new  TwitterApi();          api.postTweet("JakeWharton",  tweet);      }   } public  class  TwitterApi  {      public  void  postTweet(String  user,  String  tweet)  {          OkHttpClient  client  =  new  OkHttpClient();          HttpUrlConnection  conn  =  client.open("...");          //  ...  POST  blah  blah  blah  ...      }   }
  7. public  class  Tweeter  {      public  void  tweet(String  tweet)

     {          TwitterApi  api  =  new  TwitterApi();          api.postTweet("JakeWharton",  tweet);      }   } Tweeter  tweeter  =  new  Tweeter();   tweeter.tweet("Hello,  #Dagger  Meetup!"); public  class  TwitterApi  {      public  void  postTweet(String  user,  String  tweet)  {          OkHttpClient  client  =  new  OkHttpClient();          HttpUrlConnection  conn  =  client.open("...");          //  ...  POST  blah  blah  blah  ...      }   }
  8. public  class  TwitterApi  {      public  void  postTweet(String  user,

     String  tweet)  {          OkHttpClient  client  =  new  OkHttpClient();          HttpUrlConnection  conn  =  client.open("...");          //  ...  POST  blah  blah  blah  ...      }   }
  9. public  class  TwitterApi  {      private  final  OkHttpClient  client

     =  new  OkHttpClient();          public  void  postTweet(String  user,  String  tweet)  {          HttpUrlConnection  conn  =  client.open("...");          //  ...  POST  blah  blah  blah  ...      }   }
  10. public  class  TwitterApi  {      private  final  OkHttpClient  client;

               public  TwitterApi(OkHttpClient  client)  {          this.client  =  client;      }          public  void  postTweet(String  user,  String  tweet)  {          HttpUrlConnection  conn  =  client.open("...");          //  ...  POST  blah  blah  blah  ...      }   }
  11. public  class  Tweeter  {      public  void  tweet(String  tweet)

     {          TwitterApi  api  =  new  TwitterApi();          api.postTweet("JakeWharton",  tweet);      }   }
  12. public  class  Tweeter  {      public  void  tweet(String  tweet)

     {          TwitterApi  api  =  new  TwitterApi(new  OkHttpClient());          api.postTweet("JakeWharton",  tweet);      }   }
  13. public  class  Tweeter  {      private  final  TwitterApi  api

     =  new  TwitterApi(new  OkHttpClient());            public  void  tweet(String  tweet)  {          api.postTweet("JakeWharton",  tweet);      }   }
  14. public  class  Tweeter  {      private  final  TwitterApi  api

     =  new  TwitterApi(new  OkHttpClient());      private  final  String  user;            public  Tweeter(String  user)  {          this.user  =  user;      }            public  void  tweet(String  tweet)  {          api.postTweet(user,  tweet);      }   }
  15. Tweeter  tweeter  =  new  Tweeter("JakeWharton");   tweeter.tweet("Hello,  #Dagger  Meetup!"); tweeter.tweet("Log

     cabins!  #Dagger  @twoffice");   tweeter.tweet("mind  ==  blown.  #Dagger");   tweeter.tweet("Where’s  that  @jessewilson  character?");   tweeter.tweet("#Dagger,  #Dagger  bills  y’all");   tweeter.tweet("Leave  early  for  Beer  Hall,  anyone?  #Meetup  #Dagger");
  16. Tweeter  tweeter  =  new  Tweeter("JakeWharton");   tweeter.tweet("Hello,  #Dagger  Meetup!"); tweeter.tweet("Log

     cabins!  #Dagger  @twoffice");   tweeter.tweet("mind  ==  blown.  #Dagger");   tweeter.tweet("Where’s  that  @jessewilson  character?");   tweeter.tweet("#Dagger,  #Dagger  bills  y’all");   tweeter.tweet("Leave  early  for  Beer  Hall,  anyone?  #Meetup  #Dagger"); Timeline  timeline  =  new  Timeline("JakeWharton");   timeline.loadMore(20);   for  (Tweet  tweet  :  timeline.get())  {      System.out.println(tweet);   }
  17. public  class  Timeline  {      private  final  List<Tweet>  tweetCache

     =  new  ArrayList<>();      private  final  TwitterApi  api  =  new  TwitterApi(new  OkHttpClient());      private  final  String  user;            public  Timeline(String  user)  {          this.user  =  user;      }            public  List<Tweet>  get()  {  /*  ...  */  }      public  void  loadMore(int  amount)  {  /*  ...  */  }   }
  18. public  class  Timeline  {      private  final  List<Tweet>  tweetCache

     =  new  ArrayList<>();      private  final  TwitterApi  api;      private  final  String  user;            public  Timeline(TwitterApi  api,  String  user)  {          this.api  =  api;          this.user  =  user;      }            public  List<Tweet>  get()  {  /*  ...  */  }      public  void  loadMore(int  amount)  {  /*  ...  */  }   }
  19. public  class  Tweeter  {      private  final  TwitterApi  api

     =  new  TwitterApi(new  OkHttpClient());      private  final  String  user;            public  Tweeter(String  user)  {          this.user  =  user;      }            public  void  tweet(String  tweet)  {          api.postTweet(user,  tweet);      }   }
  20. public  class  Tweeter  {      private  final  TwitterApi  api;

         private  final  String  user;            public  Tweeter(TwitterApi  api,  String  user)  {          this.api  =  api;          this.user  =  user;      }            public  void  tweet(String  tweet)  {          api.postTweet(user,  tweet);      }   }
  21. Tweeter  tweeter  =  new  Tweeter("JakeWharton");   tweeter.tweet("Hello,  #Dagger  Meetup!");  

    ! Timeline  timeline  =  new  Timeline("JakeWharton");   timeline.loadMore(20);   for  (Tweet  tweet  :  timeline.get())  {      System.out.println(tweet);   }
  22. OkHttpClient  client  =  new  OkHttpClient();   TwitterApi  api  =  new

     TwitterApi(client);   String  user  =  "JakeWharton";       Tweeter  tweeter  =  new  Tweeter(api,  user);   tweeter.tweet("Managing  my  own  dependencies  :(");       Timeline  timeline  =  new  Timeline(api,  user);   timeline.loadMore(20);   for  (Tweet  tweet  :  timeline.get())  {      System.out.println(tweet);   }
  23. Dependency Injection • Every single app has some form of

    dependency injection • Separate the behavior from the classes required to perform it Tweeter Twitter API HTTP Client
  24. Dependency Injection • Every single app has some form of

    dependency injection • Separate the behavior from the classes required to perform it Tweeter Twitter API HTTP Client Timeline
  25. Dependency Injection • Every single app has some form of

    dependency injection • Separate the behavior from the classes required to perform it • How do we avoid the boilerplate that comes with the pattern?
  26. We used Guice • All of our Java services heavily

    use Guice • Powerful, dynamic, well-tested, wide-spread, etc...
  27. We used Guice • All of our Java services heavily

    use Guice • Powerful, dynamic, well-tested, wide-spread, etc... • Canonical standard for dependency injection
  28. We used Guice • All of our Java services heavily

    use Guice • Powerful, dynamic, well-tested, wide-spread, etc... • Canonical standard for dependency injection • Configuration problems fail at runtime
  29. We used Guice • All of our Java services heavily

    use Guice • Powerful, dynamic, well-tested, wide-spread, etc... • Canonical standard for dependency injection • Configuration problems fail at runtime • Slow initialization, slow injection, memory problems
  30. “Object Graph” Goals • Static analysis of all dependencies and

    injections • Fail as early as possible (compile-time, not runtime)
  31. “Object Graph” Goals • Static analysis of all dependencies and

    injections • Fail as early as possible (compile-time, not runtime) • Eliminate reflection on methods and annotations at runtime
  32. “Object Graph” Goals • Static analysis of all dependencies and

    injections • Fail as early as possible (compile-time, not runtime) • Eliminate reflection on methods and annotations at runtime • Have negligible memory impact
  33. “Object Graph” Development • ~5 weeks of heads-down work by

    Jesse Wilson • Bob Lee served as technical advisor
  34. “Object Graph” Development • ~5 weeks of heads-down work by

    Jesse Wilson • Bob Lee served as technical advisor • “Giant” boolean switch in our applications
  35. “Object Graph” Development • ~5 weeks of heads-down work by

    Jesse Wilson • Bob Lee served as technical advisor • “Giant” boolean switch in our applications • 2 weeks after, dropped Guice completely
  36. “Object Graph” Development • ~5 weeks of heads-down work by

    Jesse Wilson • Bob Lee served as technical advisor • “Giant” boolean switch in our applications • 2 weeks after, dropped Guice completely • Renamed to Dagger before first release
  37. Dagger • ObjectGraph: central dependency manager and injector • @Module

    + @Provides: mechanism for providing dependencies
  38. Dagger • ObjectGraph: central dependency manager and injector • @Module

    + @Provides: mechanism for providing dependencies • @Inject: mechanism for requesting dependencies
  39. Dagger • ObjectGraph: central dependency manager and injector • @Module

    + @Provides: mechanism for providing dependencies • @Inject: mechanism for requesting dependencies • Plus some other sugar, magic, and conventions
  40. Providing Dependencies • Modules are classes that provide dependencies •

    @Module annotation on the class • @Provider annotation on a method indicates that its return type is a dependency
  41. ! public  class  NetworkModule  {   !    public  OkHttpClient

     provideOkHttpClient()  {          return  new  OkHttpClient();      }       !    public  TwitterApi  provideTwitterApi(OkHttpClient  client)  {          return  new  TwitterApi(client);      }   ! }
  42. ! public  class  NetworkModule  {   !    public  OkHttpClient

     provideOkHttpClient()  {          return  new  OkHttpClient();      }       !    public  TwitterApi  provideTwitterApi(OkHttpClient  client)  {          return  new  TwitterApi(client);      }   ! } @Module
  43. ! public  class  NetworkModule  {   !    public  OkHttpClient

     provideOkHttpClient()  {          return  new  OkHttpClient();      }       !    public  TwitterApi  provideTwitterApi(OkHttpClient  client)  {          return  new  TwitterApi(client);      }   ! } ! !    @Provides   ! ! ! !    @Provides   ! ! ! @Module
  44. ! public  class  NetworkModule  {   !    public  OkHttpClient

     provideOkHttpClient()  {          return  new  OkHttpClient();      }       !    public  TwitterApi  provideTwitterApi(OkHttpClient  client)  {          return  new  TwitterApi(client);      }   ! } ! !    @Provides   ! ! ! !    @Provides   ! ! ! ! !                        @Singleton   ! ! ! !                        @Singleton   ! ! ! @Module
  45. Providing Dependencies • Modules are classes that provide dependencies •

    @Module annotation on the class provides static analysis hints • @Provider annotation on a method indicates that its return type is a dependency
  46. Providing Dependencies • Modules are classes that provide dependencies •

    @Module annotation on the class provides static analysis hints • @Provider annotation on a method indicates that its return type is a dependency • Designed to be composed together
  47. @Module   public  class  TwitterModule  {      private  final

     String  user;            public  TwitterModule(String  user)  {          this.user  =  user;      }            @Provides  @Singleton      public  Tweeter  provideTweeter(TwitterApi  api)  {          return  new  Tweeter(api,  user);      }          @Provides  @Singleton      public  Timeline  provideTimeline(TwitterApi  api)  {          return  new  Timeline(api,  user);      }   }
  48. Constructor Injection • @Inject on a single constructor • All

    constructor arguments are dependencies • Dependencies can be stored in private and final fields
  49. public  class  TweeterApp  {      private  final  Tweeter  tweeter;

         private  final  Timeline  timeline;            @Inject      public  TweeterApp(Tweeter  tweeter,  Timeline  timeline)  {          this.tweeter  =  tweeter;          this.timeline  =  timeline;      }            //  ...   }
  50. Constructor Injection • @Inject on a single constructor • All

    constructor arguments are dependencies • Dependencies can be stored in private and final fields
  51. Constructor Injection • @Inject on a single constructor • All

    constructor arguments are dependencies • Dependencies can be stored in private and final fields • Dagger must create the object
  52. Constructor Injection • @Inject on a single constructor • All

    constructor arguments are dependencies • Dependencies can be stored in private and final fields • Dagger must create the object • @Provides not required for downstream injection
  53. public  class  TweeterApp  {      @Inject  Tweeter  tweeter;  

       @Inject  Timeline  timeline;            //  ...   }
  54. public  class  TweeterActivity  extends  Activity  {      @Inject  Tweeter

     tweeter;      @Inject  Timeline  timeline;            //  ...   }
  55. Field Injection • @Inject on fields which are dependencies •

    Field may not be private or final • Injection happens after the object is “alive”
  56. Field Injection • @Inject on fields which are dependencies •

    Field may not be private or final • Injection happens after the object is “alive” • Object often must be responsible for injecting itself
  57. ObjectGraph  og  =  ObjectGraph.create(          new  NetworkModule(),

             new  TwitterModule("JakeWharton")   );
  58. ObjectGraph  og  =  ObjectGraph.create(          new  NetworkModule(),

             new  TwitterModule("JakeWharton")   ); //  Using  constructor  injection:   TweeterApp  app  =  og.get(TweeterApp.class);
  59. ObjectGraph  og  =  ObjectGraph.create(          new  NetworkModule(),

             new  TwitterModule("JakeWharton")   ); //  Using  constructor  injection:   TweeterApp  app  =  og.get(TweeterApp.class); //  Using  field  injection:   TweeterApp  app  =  new  TweeterApp();   og.inject(app);
  60. ObjectGraph  og  =  ObjectGraph.create(          new  NetworkModule(),

             new  TwitterModule("JakeWharton")   );
  61. ObjectGraph  og  =  ObjectGraph.create(          new  NetworkModule(),

             new  PersistenceModule(),          new  AccountModule()   );
  62. ObjectGraph  og  =  ObjectGraph.create(          new  NetworkModule(),

             new  PersistenceModule(),          new  AccountModule()   ); //  Inject  app  things  using  ‘og’...
  63. ObjectGraph  og  =  ObjectGraph.create(          new  NetworkModule(),

             new  PersistenceModule(),          new  AccountModule()   ); //  Later...   String  user  =  "JakeWharton"; //  Inject  app  things  using  ‘og’...
  64. ObjectGraph  og  =  ObjectGraph.create(          new  NetworkModule(),

             new  PersistenceModule(),          new  AccountModule()   ); //  Later...   String  user  =  "JakeWharton"; ObjectGraph  userOg  =  og.plus(new  TwitterModule(user)); //  Inject  app  things  using  ‘og’... //  Inject  user  things  using  ‘userOg’...
  65. Android • Entry objects are managed objects constructed by OS

    • Multiple services, activities, etc. required shared state
  66. Android • Entry objects are managed objects constructed by OS

    • Multiple services, activities, etc. required shared state • Platform is very difficult to test
  67. Android • Entry objects are managed objects constructed by OS

    • Multiple services, activities, etc. required shared state • Platform is very difficult to test • Build system allows for dynamic flavors and build types
  68. Android • Entry objects are managed objects constructed by OS

    • Multiple services, activities, etc. required shared state • Platform is very difficult to test • Build system allows for dynamic flavors and build types • Many libraries require keeping singletons or long-lived objects
  69. The ObjectGraph • Central module (dependency) manager • Injector •

    Can be extended to create “scopes” • Eagerly or lazily created on the Application by convention
  70. public  class  ExampleApp  extends  Application  {      private  ObjectGraph

     objectGraph;          @Override  public  void  onCreate()  {          super.onCreate();   !        objectGraph  =  ObjectGraph.create(              new  ExampleModule()          );      }          public  ObjectGraph  getObjectGraph()  {          return  objectGraph;      }   }
  71. public  class  ExampleActivity  extends  Activity  {      @Inject  Foo

     foo;      @Inject  Bar  bar;          @Override      protected  void  onCreate(Bundle  savedInstanceState)  {          super.onCreate(savedInstanceState);              ExampleApp  app  =  (ExampleApp)  getApplication();          app.getObjectGraph().inject(this);              //  ...      }   }
  72. The ObjectGraph • Central module (dependency) manager • Injector •

    Can be extended to create “scopes” • Eagerly or lazily created on the Application by convention
  73. The ObjectGraph • Central module (dependency) manager • Injector •

    Can be extended to create “scopes” • Eagerly or lazily created on the Application by convention • Just another object instance
  74. Listing Injection Points • All injection points must be listed

    on a module • Used for aggressive static analysis
  75. Listing Injection Points • All injection points must be listed

    on a module • Used for aggressive static analysis • Potentially not needed for full compilation...
  76. Listing Injection Points • All injection points must be listed

    on a module • Used for aggressive static analysis • Potentially not needed for full compilation... • ...but absolutely required for incremental compilation
  77. @Module   public  class  ExampleModule  {      @Provides  @Singleton

     Foo  provideFoo()  {          return  new  Foo();      }            @Provides  @Singleton  Bar  provideBar()  {          return  new  Bar();      }   }
  78. @Module(      injects  =  {        

     ExampleActivity.class      }   )   public  class  ExampleModule  {      @Provides  @Singleton  Foo  provideFoo()  {          return  new  Foo();      }            @Provides  @Singleton  Bar  provideBar()  {          return  new  Bar();      }   }
  79. Use in Android • Root ObjectGraph on Application • Activities,

    services, fragments, views obtain and inject
  80. Use in Android • Root ObjectGraph on Application • Activities,

    services, fragments, views obtain and inject • Modules and their “injects” segment parts of your app
  81. Use in Android: .plus() • Extend the graph with additional

    modules • Allows creating “scopes” of dependencies
  82. public  class  TweeterApp  extends  Application  {      private  ObjectGraph

     objectGraph;          @Override  public  void  onCreate()  {          super.onCreate();   !        objectGraph  =  ObjectGraph.create(              new  NetworkModule(),              new  PersistenceModule(),              new  AccountModule(),          );      }          public  ObjectGraph  getObjectGraph()  {          return  objectGraph;      }   }
  83. public  class  LandingActivity  extends  Activity  {      @Inject  UserManager

     userManager;          @Override      protected  void  onCreate(Bundle  savedInstanceState)  {          super.onCreate(savedInstanceState);   !        ExampleApp  app  =  (ExampleApp)  getApplication();          app.getObjectGraph().inject(this);   !        if  (userManager.hasUser())  {              //  Start  TimelineActivity,  finish,  return...          }              //  Show  log  in  /  sign  up...      }   }
  84. public  class  TimelineActivity  extends  Activity  {      @Inject  Timeline

     timeline;      @Inject  Tweeter  tweeter;   !    @Override      protected  void  onCreate(Bundle  savedInstanceState)  {          super.onCreate(savedInstanceState);   !        ExampleApp  app  =  (ExampleApp)  getApplication();          ObjectGraph  og  =  app.getObjectGraph();   !        String  user  =  og.get(UserManager.class).getUser();          //  TODO  if  user  ==  null,  finish  and  start  LandingActivity...          og.plus(new  TwitterModule(user)).inject(this);              //  Set  up  timeline  and  tweeter  UI...      }   }
  85. @Module(      injects  =  {        

     SignUpView.class,  ForgotPasswordView.class      }   )   public  class  SignUpModule  {      private  final  SignUpActivity  signUpActivity;   !    public  SignUpModule(SignUpActivity  signUpActivity)  {          this.signUpActivity  =  signUpActivity;      }   !    @Provides  @Singleton  ActionBar  provideActionBar()  {          return  signUpActivity.getActionBar();      }   }
  86. public  class  SignUpActivity  class  Activity  {      private  final

     ObjectGraph  childOg;   !    @Override      protected  void  onCreate(Bundle  savedInstanceState)  {          super.onCreate(savedInstanceState);   !        ExampleApp  app  =  (ExampleApp)  getApplication();          ObjectGraph  og  =  app.getObjectGraph();   !        childOg  =  og.plus(new  SignUpModule(this));   !        //  Content  set  up  and  injection...      }   }
  87. public  class  SignUpView  class  LinearLayout  {      @Inject  ActionBar

     actionBar;   !    public  SignUpView(Context  context,  AttributeSet  attrs)  {          super(context,  attrs);          //  Note:  Injection  happens  by  parent  activity.      }   !    @Override  public  void  onAttachedToWindow()  {          super.onAttachedToWindow();          actionBar.setTitle(R.string.sign_up);      }   }
  88. Use in Android: overrides • Modules whose dependencies override others

    • Only apply in the same ObjectGraph • Useful for customizing flavors and testing
  89. public  class  Timeline  {      private  final  List<Tweet>  tweetCache

     =  new  ArrayList<>();      private  final  TwitterApi  api;      private  final  String  user;            public  Timeline(TwitterApi  api,  String  user)  {          this.api  =  api;          this.user  =  user;      }            public  List<Tweet>  get()  {  /*  ...  */  }      public  void  loadMore(int  amount)  {  /*  ...  */  }   }
  90. public  class  MockTimeline  extends  Timeline  {      private  final

     List<Tweet>  tweets  =  new  ArrayList<>();            @Inject  MockTimeline()  {          tweets.add(new  Tweet("MockUser",  "Hello,  mock  data!");      }            @Override  public  List<Tweet>  get()  {          return  tweets;      }   !    public  void  addTweet(Tweet  tweet)  {          tweets.add(new  Tweet("MockUser",  tweet),  0);      }   !    @Override  public  void  loadMore(int  amount)  {}   }
  91. public  class  Tweeter  {      private  final  TwitterApi  api;

         private  final  String  user;            public  Tweeter(TwitterApi  api,  String  user)  {          this.api  =  api;          this.user  =  user;      }            public  void  tweet(String  tweet)  {          api.postTweet(user,  tweet);      }   }
  92. public  class  MockTweeter  extends  Tweeter  {      private  final

     MockTimeline  timeline;            @Inject  MockTweeter(MockTimeline  timeline)  {          this.timeline  =  timeline;      }            @Override  public  void  tweet(String  tweet)  {          timeline.addTweet(tweet);      }   }
  93. @Module(      overrides  =  true   )   public

     class  MockTwitterModule  {      @Provides  @Singleton      public  Tweeter  provideTweeter(MockTweeter  mockTweeter)  {          return  mockTweeter;      }          @Provides  @Singleton      public  Timeline  provideTimeline(MockTimeline  mockTimeline)  {          return  mockTimeline;      }   }
  94. ObjectGraph  og  =  ObjectGraph.create(      new  NetworkModule(),    

     new  TwitterModule("JakeWharton"),            new  MockTwitterModule()   );
  95. Timeline  timeline  =  /*  injected  */   Tweeter  tweeter  =

     /*  injected  */ for  (Tweet  tweet  :  timeline.get())  {      System.out.println(tweet);   }   //    MockUser:  Hello,  mock  data!
  96. Timeline  timeline  =  /*  injected  */   Tweeter  tweeter  =

     /*  injected  */ tweeter.tweet("Showing  off  more  mock  data!  #Dagger"); for  (Tweet  tweet  :  timeline.get())  {      System.out.println(tweet);   }   //    MockUser:  Hello,  mock  data!
  97. Timeline  timeline  =  /*  injected  */   Tweeter  tweeter  =

     /*  injected  */ for  (Tweet  tweet  :  timeline.get())  {      System.out.println(tweet);   }   //  MockUser:  Showing  off  more  mock  data!  #Dagger   //  MockUser:  Hello,  mock  data! tweeter.tweet("Showing  off  more  mock  data!  #Dagger"); for  (Tweet  tweet  :  timeline.get())  {      System.out.println(tweet);   }   //    MockUser:  Hello,  mock  data!
  98. Mock Mode • Modules which override all network-calling classes •

    Alternate implementations of network-calling classes which emulate a remote server but in-memory
  99. Mock Mode • Modules which override all network-calling classes •

    Alternate implementations of network-calling classes which emulate a remote server but in-memory • Fake images and data included in debug builds
  100. //  src/release/java   ! final  class  Modules  {    

     static  Object[]  list()  {          return  new  Object[]  {              new  WalletModule()          };      }   }
  101. //  src/release/java   ! final  class  Modules  {    

     static  Object[]  list()  {          return  new  Object[]  {              new  WalletModule()          };      }   } //  src/debug/java   ! final  class  Modules  {      static  Object[]  list()  {          return  new  Object[]  {              new  WalletModule(),              new  DebugWalletModule()          };      }   }
  102. public  class  WalletApp  extends  Application  {      private  ObjectGraph

     objectGraph;          @Override  public  void  onCreate()  {          super.onCreate();   !        objectGraph  =  ObjectGraph.create(Modules.list());      }          public  ObjectGraph  getObjectGraph()  {          return  objectGraph;      }   }
  103. Debug Drawer • Provides quick access to developer options and

    information • Completely hidden from normal UI
  104. Debug Drawer • Provides quick access to developer options and

    information • Completely hidden from normal UI • Contains controls for changing app behavior
  105. U+2020 Sample App • Dagger • Retrofit • RxJava •

    Picasso • OkHttp • Butter Knife • Timber • Build Flavors
  106. U+2020 Sample App • Dagger • Retrofit • RxJava •

    Picasso • OkHttp • Butter Knife • Timber • Build Flavors http://github.com/JakeWharton/u2020/
  107. Dependency Injection • Do NOT ignore the pattern • Do

    NOT make every class use the pattern
  108. Dependency Injection • Do NOT ignore the pattern • Do

    NOT make every class use the pattern • Do NOT store dependencies as static fields
  109. “Avoid Dependency Injection” Using a dependency injection framework such as

    Guice or RoboGuice may be attractive because they can simplify the code you write and provide an adaptive environment that's useful for testing and other configuration changes. However, these frameworks tend to perform a lot of process initialization by scanning your code for annotations, which can require significant amounts of your code to be mapped into RAM even though you don't need it. d.android.com/training/articles/memory.html#DependencyInjection
  110. Dagger Performance • Annotation processor generates code to fulfill dependencies

    • Happens automatically inside of javac • Zero reflection on methods or fields
  111. Dagger Performance • Annotation processor generates code to fulfill dependencies

    • Happens automatically inside of javac • Zero reflection on methods or fields • Debugger and developer friendly
  112. The Future • Zero reflection... everywhere • Death to injects

    list • Components encapsulate dependencies
  113. The Future • Zero reflection... everywhere • Death to injects

    list • Components encapsulate dependencies • Scopes with dedicated annotations
  114. The Future • Zero reflection... everywhere • Death to injects

    list • Components encapsulate dependencies • Scopes with dedicated annotations • http://squ.re/dagger2