Slide 1

Slide 1 text

Dagger Jake Wharton

Slide 2

Slide 2 text

#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

Slide 3

Slide 3 text

Dependency Injection

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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");

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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)  {  /*  ...  */  } }

Slide 24

Slide 24 text

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)  {  /*  ...  */  } }

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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?

Slide 32

Slide 32 text

We used Guice

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

No content

Slide 39

Slide 39 text

“ObjectGraph” Goals

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

“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

Slide 43

Slide 43 text

“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

Slide 44

Slide 44 text

“ObjectGraph” Development

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

“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

Slide 49

Slide 49 text

“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

Slide 50

Slide 50 text

Dagger

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

Dagger

Slide 54

Slide 54 text

Dagger • ObjectGraph: central dependency manager and injector

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

Providing Dependencies

Slide 59

Slide 59 text

Providing Dependencies • Modules are classes that provide dependencies

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

Providing Dependencies

Slide 67

Slide 67 text

Providing Dependencies OkHttpClient TwitterApi

Slide 68

Slide 68 text

Providing Dependencies OkHttpClient TwitterApi NetworkModule#provideOkHttpClient NetworkModule#provideTwitterApi

Slide 69

Slide 69 text

Providing Dependencies OkHttpClient TwitterApi NetworkModule#provideOkHttpClient NetworkModule#provideTwitterApi

Slide 70

Slide 70 text

Providing Dependencies OkHttpClient TwitterApi NetworkModule#provideOkHttpClient NetworkModule#provideTwitterApi

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

Providing Dependencies OkHttpClient TwitterApi NetworkModule#provideOkHttpClient NetworkModule#provideTwitterApi

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

Requesting Dependencies

Slide 77

Slide 77 text

Requesting Dependencies • @Inject annotation required

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

Constructor Injection

Slide 80

Slide 80 text

Constructor Injection • @Inject on a single constructor

Slide 81

Slide 81 text

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

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

Field Injection

Slide 88

Slide 88 text

Field Injection • @Inject on fields which are dependencies

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

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

Slide 91

Slide 91 text

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

Slide 92

Slide 92 text

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

Slide 93

Slide 93 text

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

Slide 94

Slide 94 text

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

Slide 95

Slide 95 text

The ObjectGraph

Slide 96

Slide 96 text

The ObjectGraph • Central module (dependency) manager

Slide 97

Slide 97 text

The ObjectGraph • Central module (dependency) manager • Injector

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

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

Slide 100

Slide 100 text

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

Slide 101

Slide 101 text

The ObjectGraph • Central module (dependency) manager • Injector

Slide 102

Slide 102 text

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

Slide 103

Slide 103 text

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

Slide 104

Slide 104 text

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

Slide 105

Slide 105 text

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

Slide 106

Slide 106 text

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

Slide 107

Slide 107 text

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

Slide 108

Slide 108 text

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

Slide 109

Slide 109 text

OkHttpClient TwitterApi NetworkModule

Slide 110

Slide 110 text

OkHttpClient TwitterApi NetworkModule PersistenceModule . . . AccountModule . . .

Slide 111

Slide 111 text

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

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

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

Slide 114

Slide 114 text

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

Slide 115

Slide 115 text

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

Slide 116

Slide 116 text

Android

Slide 117

Slide 117 text

Android • Entry objects are managed objects constructed by OS

Slide 118

Slide 118 text

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

Slide 119

Slide 119 text

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

Slide 120

Slide 120 text

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

Slide 121

Slide 121 text

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

Slide 122

Slide 122 text

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

Slide 123

Slide 123 text

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

Slide 124

Slide 124 text

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

Slide 125

Slide 125 text

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

Slide 126

Slide 126 text

Listing Injection Points

Slide 127

Slide 127 text

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

Slide 128

Slide 128 text

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

Slide 129

Slide 129 text

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

Slide 130

Slide 130 text

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

Slide 131

Slide 131 text

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

Slide 132

Slide 132 text

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

Slide 133

Slide 133 text

Use in Android

Slide 134

Slide 134 text

Use in Android • Root ObjectGraph on Application

Slide 135

Slide 135 text

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

Slide 136

Slide 136 text

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

Slide 137

Slide 137 text

Use in Android: .plus()

Slide 138

Slide 138 text

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

Slide 139

Slide 139 text

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

Slide 140

Slide 140 text

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

Slide 141

Slide 141 text

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

Slide 142

Slide 142 text

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

Slide 143

Slide 143 text

Use in Android: .plus()

Slide 144

Slide 144 text

Use in Android: .plus()

Slide 145

Slide 145 text

Use in Android: .plus()

Slide 146

Slide 146 text

Sign Up Use in Android: .plus()

Slide 147

Slide 147 text

Use in Android: .plus() Forgot Password

Slide 148

Slide 148 text

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

Slide 149

Slide 149 text

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

Slide 150

Slide 150 text

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

Slide 151

Slide 151 text

Use in Android: overrides

Slide 152

Slide 152 text

Use in Android: overrides • Modules whose dependencies override others

Slide 153

Slide 153 text

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

Slide 154

Slide 154 text

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

Slide 155

Slide 155 text

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)  {  /*  ...  */  } }

Slide 156

Slide 156 text

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

Slide 157

Slide 157 text

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

Slide 158

Slide 158 text

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

Slide 159

Slide 159 text

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

Slide 160

Slide 160 text

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

Slide 161

Slide 161 text

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

Slide 162

Slide 162 text

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

Slide 163

Slide 163 text

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!

Slide 164

Slide 164 text

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!

Slide 165

Slide 165 text

Mock Mode

Slide 166

Slide 166 text

Mock Mode • Modules which override all network-calling classes

Slide 167

Slide 167 text

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

Slide 168

Slide 168 text

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

Slide 169

Slide 169 text

No content

Slide 170

Slide 170 text

No content

Slide 171

Slide 171 text

No content

Slide 172

Slide 172 text

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

Slide 173

Slide 173 text

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

Slide 174

Slide 174 text

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

Slide 175

Slide 175 text

Debug Drawer

Slide 176

Slide 176 text

Debug Drawer • Provides quick access to developer options and information

Slide 177

Slide 177 text

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

Slide 178

Slide 178 text

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

Slide 179

Slide 179 text

No content

Slide 180

Slide 180 text

No content

Slide 181

Slide 181 text

No content

Slide 182

Slide 182 text

U+2020 Sample App

Slide 183

Slide 183 text

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

Slide 184

Slide 184 text

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

Slide 185

Slide 185 text

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

Slide 186

Slide 186 text

Dependency Injection

Slide 187

Slide 187 text

Dependency Injection • Do NOT ignore the pattern

Slide 188

Slide 188 text

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

Slide 189

Slide 189 text

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

Slide 190

Slide 190 text

“Avoid Dependency Injection”

Slide 191

Slide 191 text

“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

Slide 192

Slide 192 text

Dagger Performance

Slide 193

Slide 193 text

Dagger Performance • Annotation processor generates code to fulfill dependencies

Slide 194

Slide 194 text

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

Slide 195

Slide 195 text

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

Slide 196

Slide 196 text

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

Slide 197

Slide 197 text

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

Slide 198

Slide 198 text

Questions?

Slide 199

Slide 199 text

squareup.com/careers