$30 off During Our Annual Pro Sale. View Details »

Android Apps with Dagger (Devoxx 2013)

Android Apps with Dagger (Devoxx 2013)

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

Watch the talk: http://parleys.com/play/529bde2ce4b0e619540cc3ae

Jake Wharton
PRO

November 14, 2013
Tweet

More Decks by Jake Wharton

Other Decks in Technology

Transcript

  1. Dagger
    Jake Wharton

    View Slide

  2. #DV13 #Dagger
    DV13 #Dagger
    #DV13 #Dagger #DV13 #Dagger
    #DV13 #Dagger #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger #DV13 #Dagger
    #DV13 #Dagger
    Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    ger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13
    #D
    #Dagger
    #DV13 #Dagger
    #DV13 #Dagg
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    V13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagge
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Da
    #DV13 #Dagger #DV13 #Dagger
    #DV13 #Da
    ger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagge
    #DV13 #Dagger
    #DV13 #Dagger
    V13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    er
    #D
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger #DV13 #D
    #DV13 #Dagger
    #DV13 #Dagg
    #DV13 #Dagger
    13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #D
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    #DV13 #Dagger
    3 #Dagger
    gger
    #DV13 #Dagger
    #DV13 #Dagger

    View Slide

  3. Dependency Injection

    View Slide

  4. Dependency Injection
    • Every single app has some form of dependency injection

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  10. 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  ...
       }
    }

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  14. 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  ...
       }
    }

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  18. 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);
       }
    }

    View Slide

  19. Tweeter  tweeter  =  new  Tweeter();
    tweeter.tweet("Hello,  Devoxx  2013!  #DV13  #Dagger");

    View Slide

  20. Tweeter  tweeter  =  new  Tweeter("JakeWharton");
    tweeter.tweet("Hello,  Devoxx  2013!  #DV13  #Dagger");

    View Slide

  21. Tweeter  tweeter  =  new  Tweeter("JakeWharton");
    tweeter.tweet("Hello,  Devoxx  2013!  #DV13  #Dagger");
    tweeter.tweet("Devoxx  2013  is  amazing!  #DV13");
    tweeter.tweet("mind  ==  blown.  #DV13  #Dagger");
    tweeter.tweet("OMG  you  better  be  at  Devoxx!");
    tweeter.tweet("#Devoxx  #Dagger  #Devoxx  #Dagger  #Devoxx");
    tweeter.tweet("Hungover...  #DV13");

    View Slide

  22. Tweeter  tweeter  =  new  Tweeter("JakeWharton");
    tweeter.tweet("Hello,  Devoxx  2013!  #DV13  #Dagger");
    tweeter.tweet("Devoxx  2013  is  amazing!  #DV13");
    tweeter.tweet("mind  ==  blown.  #DV13  #Dagger");
    tweeter.tweet("OMG  you  better  be  at  Devoxx!");
    tweeter.tweet("#Devoxx  #Dagger  #Devoxx  #Dagger  #Devoxx");
    tweeter.tweet("Hungover...  #DV13");
    Timeline  timeline  =  new  Timeline("JakeWharton");
    timeline.loadMore(20);
    for  (Tweet  tweet  :  timeline.get())  {
       System.out.println(tweet);
    }

    View Slide

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

    View Slide

  24. public  class  Timeline  {
       private  final  List  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  get()  {  /*  ...  */  }
       public  void  loadMore(int  amount)  {  /*  ...  */  }
    }

    View Slide

  25. 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);
       }
    }

    View Slide

  26. 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);
       }
    }

    View Slide

  27. Tweeter  tweeter  =  new  Tweeter("JakeWharton");
    tweeter.tweet("Hello,  Devoxx  2013!");
    Timeline  timeline  =  new  Timeline("JakeWharton");
    timeline.loadMore(20);
    for  (Tweet  tweet  :  timeline.get())  {
       System.out.println(tweet);
    }

    View Slide

  28. OkHttpClient  client  =  new  OkHttpClient();
    TwitterApi  api  =  new  TwitterApi(client);
    String  user  =  "JakeWharton";
     
    Tweeter  tweeter  =  new  Tweeter(api,  user);
    tweeter.tweet("Man,  this  takes  a  lot  of  code!");
     
    Timeline  timeline  =  new  Timeline(api,  user);
    timeline.loadMore(20);
    for  (Tweet  tweet  :  timeline.get())  {
       System.out.println(tweet);
    }

    View Slide

  29. 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

    View Slide

  30. 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

    View Slide

  31. 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?

    View Slide

  32. We used Guice

    View Slide

  33. We used Guice
    • All of our Java services heavily use Guice

    View Slide

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

    View Slide

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

    View Slide

  36. 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

    View Slide

  37. 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

    View Slide

  38. View Slide

  39. “ObjectGraph” Goals

    View Slide

  40. “ObjectGraph” Goals
    • Static analysis of all dependencies and injections

    View Slide

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

    View Slide

  42. “ObjectGraph” 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

    View Slide

  43. “ObjectGraph” 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

    View Slide

  44. “ObjectGraph” Development

    View Slide

  45. “ObjectGraph” Development
    • ~5 weeks of heads-down work by Jesse Wilson

    View Slide

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

    View Slide

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

    View Slide

  48. “ObjectGraph” 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

    View Slide

  49. “ObjectGraph” 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

    View Slide

  50. Dagger

    View Slide

  51. Dagger
    Tweeter
    Twitter API HTTP Client
    User Manager
    Shared
    Preferences
    Account
    Manager

    View Slide

  52. Dagger
    Tweeter
    Twitter API HTTP Client
    User Manager
    Shared
    Preferences
    DAG-er
    Account
    Manager

    View Slide

  53. Dagger

    View Slide

  54. Dagger
    • ObjectGraph: central dependency manager and injector

    View Slide

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

    View Slide

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

    View Slide

  57. 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

    View Slide

  58. Providing Dependencies

    View Slide

  59. Providing Dependencies
    • Modules are classes that provide dependencies

    View Slide

  60. Providing Dependencies
    • Modules are classes that provide dependencies
    • @Module annotation on the class

    View Slide

  61. 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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  66. Providing Dependencies

    View Slide

  67. Providing Dependencies
    OkHttpClient
    TwitterApi

    View Slide

  68. Providing Dependencies
    OkHttpClient
    TwitterApi
    NetworkModule#provideOkHttpClient
    NetworkModule#provideTwitterApi

    View Slide

  69. Providing Dependencies
    OkHttpClient
    TwitterApi
    NetworkModule#provideOkHttpClient
    NetworkModule#provideTwitterApi

    View Slide

  70. Providing Dependencies
    OkHttpClient
    TwitterApi
    NetworkModule#provideOkHttpClient
    NetworkModule#provideTwitterApi

    View Slide

  71. 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

    View Slide

  72. 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

    View Slide

  73. @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);
       }
    }

    View Slide

  74. Providing Dependencies
    OkHttpClient
    TwitterApi
    NetworkModule#provideOkHttpClient
    NetworkModule#provideTwitterApi

    View Slide

  75. Providing Dependencies
    OkHttpClient
    TwitterApi
    NetworkModule#provideOkHttpClient
    NetworkModule#provideTwitterApi
    Tweeter
    Timeline
    TwitterModule#provideTweeter
    TwitterModule#provideTimeline

    View Slide

  76. Requesting Dependencies

    View Slide

  77. Requesting Dependencies
    • @Inject annotation required

    View Slide

  78. Requesting Dependencies
    • @Inject annotation required
    • Field injection and constructor injection only

    View Slide

  79. Constructor Injection

    View Slide

  80. Constructor Injection
    • @Inject on a single constructor

    View Slide

  81. Constructor Injection
    • @Inject on a single constructor
    • All constructor arguments are dependencies

    View Slide

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

    View Slide

  83. public  class  TweeterApp  {
       private  final  Tweeter  tweeter;
       private  final  Timeline  timeline;
       
       @Inject
       public  TweeterApp(Tweeter  tweeter,  Timeline  timeline)  {
           this.tweeter  =  tweeter;
           this.timeline  =  timeline;
       }
       
       //  ...
    }

    View Slide

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

    View Slide

  85. 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

    View Slide

  86. 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

    View Slide

  87. Field Injection

    View Slide

  88. Field Injection
    • @Inject on fields which are dependencies

    View Slide

  89. Field Injection
    • @Inject on fields which are dependencies
    • Field may not be private or final

    View Slide

  90. public  class  TweeterApp  {
       @Inject  Tweeter  tweeter;
       @Inject  Timeline  timeline;
       
       //  ...
    }

    View Slide

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

    View Slide

  92. Field Injection
    • @Inject on fields which are dependencies
    • Field may not be private or final

    View Slide

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

    View Slide

  94. 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

    View Slide

  95. The ObjectGraph

    View Slide

  96. The ObjectGraph
    • Central module (dependency) manager

    View Slide

  97. The ObjectGraph
    • Central module (dependency) manager
    • Injector

    View Slide

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

    View Slide

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

    View Slide

  100. 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);

    View Slide

  101. The ObjectGraph
    • Central module (dependency) manager
    • Injector

    View Slide

  102. The ObjectGraph
    • Central module (dependency) manager
    • Injector
    • Can be extended to create “scopes”

    View Slide

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

    View Slide

  104. ObjectGraph  og  =  ObjectGraph.create(
       new  NetworkModule()
    );

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  108. 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’...

    View Slide

  109. OkHttpClient
    TwitterApi
    NetworkModule

    View Slide

  110. OkHttpClient
    TwitterApi
    NetworkModule PersistenceModule
    .
    .
    .
    AccountModule
    .
    .
    .

    View Slide

  111. OkHttpClient
    TwitterApi
    NetworkModule PersistenceModule
    .
    .
    .
    AccountModule
    .
    .
    .
    og

    View Slide

  112. OkHttpClient
    TwitterApi
    NetworkModule PersistenceModule
    .
    .
    .
    AccountModule
    .
    .
    .
    UserModule
    Tweeter
    Timeline
    og

    View Slide

  113. OkHttpClient
    TwitterApi
    NetworkModule PersistenceModule
    .
    .
    .
    AccountModule
    .
    .
    .
    UserModule
    Tweeter
    Timeline
    og
    userOg

    View Slide

  114. OkHttpClient
    TwitterApi
    NetworkModule PersistenceModule
    .
    .
    .
    AccountModule
    .
    .
    .
    UserModule
    Tweeter
    Timeline
    og
    userOg

    View Slide

  115. OkHttpClient
    TwitterApi
    NetworkModule PersistenceModule
    .
    .
    .
    AccountModule
    .
    .
    .
    UserModule
    Tweeter
    Timeline
    og
    userOg

    View Slide

  116. Android

    View Slide

  117. Android
    • Entry objects are managed objects constructed by OS

    View Slide

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

    View Slide

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

    View Slide

  120. 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

    View Slide

  121. 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

    View Slide

  122. The ObjectGraph
    • Central module (dependency) manager
    • Injector
    • Can be extended to create “scopes”

    View Slide

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

    View Slide

  124. public  class  ExampleApp  extends  Application  {
       private  ObjectGraph  objectGraph;
     
       @Override  public  void  onCreate()  {
           super.onCreate();
           objectGraph  =  ObjectGraph.create(
               new  ExampleModule()
           );
       }
     
       public  ObjectGraph  getObjectGraph()  {
           return  objectGraph;
       }
    }

    View Slide

  125. 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);
     
           //  ...
       }
    }

    View Slide

  126. Listing Injection Points

    View Slide

  127. Listing Injection Points
    • All injection points must be listed on a module

    View Slide

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

    View Slide

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

    View Slide

  130. 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

    View Slide

  131. @Module
    public  class  ExampleModule  {
       @Provides  @Singleton  Foo  provideFoo()  {
           return  new  Foo();
       }
       
       @Provides  @Singleton  Bar  provideBar()  {
           return  new  Bar();
       }
    }

    View Slide

  132. @Module(
       injects  =  {
           ExampleActivity.class
       }
    )
    public  class  ExampleModule  {
       @Provides  @Singleton  Foo  provideFoo()  {
           return  new  Foo();
       }
       
       @Provides  @Singleton  Bar  provideBar()  {
           return  new  Bar();
       }
    }

    View Slide

  133. Use in Android

    View Slide

  134. Use in Android
    • Root ObjectGraph on Application

    View Slide

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

    View Slide

  136. Use in Android
    • Root ObjectGraph on Application
    • Activities, services, fragments, views obtain and inject
    • Modules and their “injects” segment parts of your app

    View Slide

  137. Use in Android: .plus()

    View Slide

  138. Use in Android: .plus()
    • Extend the graph with additional modules

    View Slide

  139. Use in Android: .plus()
    • Extend the graph with additional modules
    • Allows creating “scopes” of dependencies

    View Slide

  140. 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;
       }
    }

    View Slide

  141. 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...
       }
    }

    View Slide

  142. 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...
       }
    }

    View Slide

  143. Use in Android: .plus()

    View Slide

  144. Use in Android: .plus()

    View Slide

  145. Use in Android: .plus()

    View Slide

  146. Sign Up
    Use in Android: .plus()

    View Slide

  147. Use in Android: .plus()
    Forgot
    Password

    View Slide

  148. @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();
       }
    }

    View Slide

  149. 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...
       }
    }

    View Slide

  150. 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);
       }
    }

    View Slide

  151. Use in Android: overrides

    View Slide

  152. Use in Android: overrides
    • Modules whose dependencies override others

    View Slide

  153. Use in Android: overrides
    • Modules whose dependencies override others
    • Only apply in the same ObjectGraph

    View Slide

  154. Use in Android: overrides
    • Modules whose dependencies override others
    • Only apply in the same ObjectGraph
    • Useful for customizing flavors and testing

    View Slide

  155. public  class  Timeline  {
       private  final  List  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  get()  {  /*  ...  */  }
       public  void  loadMore(int  amount)  {  /*  ...  */  }
    }

    View Slide

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

    View Slide

  157. 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);
       }
    }

    View Slide

  158. 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);
       }
    }

    View Slide

  159. @Module(
       overrides  =  true
    )
    public  class  MockTwitterModule  {
       @Provides  @Singleton
       public  Tweeter  provideTweeter(MockTweeter  mockTweeter)  {
           return  mockTweeter;
       }
     
       @Provides  @Singleton
       public  Timeline  provideTimeline(MockTimeline  mockTimeline)  {
           return  mockTimeline;
       }
    }

    View Slide

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

    View Slide

  161. Timeline  timeline  =  /*  injected  */
    Tweeter  tweeter  =  /*  injected  */

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  165. Mock Mode

    View Slide

  166. Mock Mode
    • Modules which override all network-calling classes

    View Slide

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

    View Slide

  168. 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

    View Slide

  169. View Slide

  170. View Slide

  171. View Slide

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

    View Slide

  173. //  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()
           };
       }
    }

    View Slide

  174. public  class  WalletApp  extends  Application  {
       private  ObjectGraph  objectGraph;
     
       @Override  public  void  onCreate()  {
           super.onCreate();
           objectGraph  =  ObjectGraph.create(Modules.list());
       }
     
       public  ObjectGraph  getObjectGraph()  {
           return  objectGraph;
       }
    }

    View Slide

  175. Debug Drawer

    View Slide

  176. Debug Drawer
    • Provides quick access to developer options and information

    View Slide

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

    View Slide

  178. Debug Drawer
    • Provides quick access to developer options and information
    • Completely hidden from normal UI
    • Contains controls for changing app behavior

    View Slide

  179. View Slide

  180. View Slide

  181. View Slide

  182. U+2020 Sample App

    View Slide

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

    View Slide

  184. U+2020 Sample App
    • Dagger
    • Retrofit
    • RxJava
    • Picasso
    • OkHttp
    • Butter Knife
    • Timber
    • Build Flavors
    http://github.com/JakeWharton/u2020/

    View Slide

  185. U+2020 Sample App
    • Dagger
    • Retrofit
    • RxJava
    • Picasso
    • OkHttp
    • Butter Knife
    • Timber
    • Build Flavors
    http://github.com/JakeWharton/u2020/
    #Soon

    View Slide

  186. Dependency Injection

    View Slide

  187. Dependency Injection
    • Do NOT ignore the pattern

    View Slide

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

    View Slide

  189. Dependency Injection
    • Do NOT ignore the pattern
    • Do NOT make every class use the pattern
    • Do NOT store dependencies as static fields

    View Slide

  190. “Avoid Dependency Injection”

    View Slide

  191. “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

    View Slide

  192. Dagger Performance

    View Slide

  193. Dagger Performance
    • Annotation processor generates code to fulfill dependencies

    View Slide

  194. Dagger Performance
    • Annotation processor generates code to fulfill dependencies
    • Happens automatically inside of javac

    View Slide

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

    View Slide

  196. Dagger Performance
    • Annotation processor generates code to fulfill dependencies
    • Happens automatically inside of javac
    • Zero reflection on methods or fields
    • Debugger and developer friendly

    View Slide

  197. http://square.github.io/dagger/

    View Slide

  198. Questions?

    View Slide

  199. squareup.com/careers

    View Slide