Slide 1

Slide 1 text

Android with Dagger 2 ⿈黃千碩 / Kros iOS/Android Developer

Slide 2

Slide 2 text

Dependency Injection • 中⽂文 - 相依性注⼊入? • No “new”, dependencies come to you.

Slide 3

Slide 3 text

Dependency Injection • ⼀一種 Design Pattern • 最快速,且不⽤用任何 Liberary 即可達成 • 其實每個 app 中都已經有實作 DJ

Slide 4

Slide 4 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(); Request request = // TODO build POST request… client.newCall(request).execute(); } Tweeter tweeter = new Tweeter();
 tweeter.tweet("Hello, #Devoxx 2014!");

Slide 5

Slide 5 text

public class TwitterApi {
 private final OkHttpClient client = new OkHttpClient(); public void postTweet(String user, String tweet) { Request request = // TODO build POST request client.newCall(request).execute(); } }

Slide 6

Slide 6 text

public class TwitterApi {
 private final OkHttpClient client; public TwitterApi(OkHttpClient client) { this.client = client; } public void postTweet(String user, String tweet) { Request request = // TODO build POST request client.newCall(request).execute(); } }

Slide 7

Slide 7 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 8

Slide 8 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);
 } } Tweeter tweeter = new Tweeter("JakeWharton");
 tweeter.tweet("Hello, #Devoxx 2014!");
 tweeter.tweet("#Hungover #Dagger");


Slide 9

Slide 9 text

Libraries • Spring • Guice • Dagger (v1) • PicoContainer • CDI

Slide 10

Slide 10 text

Guice • Developed at Google by Bob Lee, later Jesse Wilson, others. • Adopted and maintained by Java Core Libraries team. Powerful, dynamic, well-tested, wide- spread, etc... • Configuration problems occur at runtime. • Slow initialization, slow injection, memory concerns.

Slide 11

Slide 11 text

Dagger (v1) • Developed at Square by Jesse Wilson advised by Bob Lee. • Initially targeted at highly resource constrained environments. • Static analysis of all dependencies and injection points. • Fail as early as possible (compile-time, not runtime) • Eliminate reflection on methods, fields, and annotations.

Slide 12

Slide 12 text

Dagger (v2) • Proposed and implemented by Java Core Libraries team. • Eliminate runtime library and generated code overhead. • Shift remaining runtime analysis to compile time. • Scoping with annotations and associated static analysis.

Slide 13

Slide 13 text

Dagger API • @Module + @Provides: 提供相依性的機制 • @Inject: 要求提供相依性 • @Component: modules 與 injections 之間的橋 樑,讓兩者能互通 • 另外有⼀一些語法糖可以使⽤用,使⽤用起來更⽅方便 • 被設計成可以拆成許多⼩小元件,並組合起來使⽤用

Slide 14

Slide 14 text

Providing Dependencies • Modules 是⼀一些 classes,⽽而這些 classes 中的 methods 提供相依性。 • 必須在 class 上加上 @Module • 必須在每個 method 上加上 @Provides

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

OkHttpClient Providing Dependencies NetworkModule#provideOkHttpClient TwitterApi NetworkModule#provideTwitterApi

Slide 20

Slide 20 text

OkHttpClient Providing Dependencies NetworkModule#provideOkHttpClient TwitterApi NetworkModule#provideTwitterApi

Slide 21

Slide 21 text

OkHttpClient Providing Dependencies NetworkModule#provideOkHttpClient TwitterApi NetworkModule#provideTwitterApi

Slide 22

Slide 22 text

Providing Dependencies • Modules 是⼀一些 classes,⽽而這些 classes 中的 methods 提供相依性。 • 必須在 class 上加上 @Module • 必須在每個 method 上加上 @Provides • Modules 可以拆開成很多 module,也可以組合在 ⼀一起使⽤用

Slide 23

Slide 23 text

@Module
 public class TwitterModule { private final String user; public TwitterModule(String user) {
 this.user = user; } @Provides @Singleton Tweeter provideTweeter(TwitterApi api) { return new Tweeter(api, user); } @Provides @Singleton Timeline provideTimeline(TwitterApi api) { return new Tweeter(api, user); } }

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

Requesting Dependencies • 必須要有 @Inject 的 annotation • 有三種 inject ⽅方式 • Constructor, field, and method injection.

Slide 56

Slide 56 text

Constructor Injection • 在 Constructor 加上 @Inject • 表⽰示 Constructor 的參數需要 dependency • 這些參數可以被使⽤用在 private 或 final fields.

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

Method Injection • 在 methods 上加上 @Inject • 表⽰示 method 的參數需要 dependency • Injection 發⽣生在物件被完全建⽴立之後 • 只有⼀一個合理的 use case: passing ‘this’ to a dependency.

Slide 59

Slide 59 text

public class TwitterApplication { private final Tweeter tweeter; private final Timeline timeline; @Inject
 public TwitterApplication(Tweeter tweeter, Timeline timeline) {
 this.tweeter = tweeter; this.timeline = timeline;
 } @Inject
 public void enableStreaming(Streaming streaming) {
 streaming.register(this); } }

Slide 60

Slide 60 text

Field Injection • 在 fields 上加上 @Inject • Field 不能為 private 或是 final • Injection 發⽣生在物件被完全建⽴立之後 • 在 android 中最常⾒見到

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

Components • Modules 與 injections 之間的橋樑,讓兩者能互 通 • Component 為 injector,實際發⽣生 inject 的⼈人 • Scope 的概念

Slide 63

Slide 63 text

@Singleton @Component(modules = { NetworkModule.class,
 TwitterModule.class,
 !})
 public interface TwitterComponent { 
 }

Slide 64

Slide 64 text

@Singleton @Component(modules = { NetworkModule.class,
 TwitterModule.class,
 !})
 public interface TwitterComponent { Tweeter tweeter();
 Timeline timeline(); }

Slide 65

Slide 65 text

TwitterComponent component = DaggerTwitterComponent.builder() .twitterModule(new TwitterModule(“JakeWharton")) .build();

Slide 66

Slide 66 text

TwitterComponent component = DaggerTwitterComponent.builder() .twitterModule(new TwitterModule(“JakeWharton")) .build(); @Module
 public class TwitterModule { private final String user; public TwitterModule(String user) {
 this.user = user; } // …

Slide 67

Slide 67 text

TwitterComponent component = DaggerTwitterComponent.builder() .twitterModule(new TwitterModule(“JakeWharton")) .build(); Tweeter tweeter = component.tweeter(); tweeter.tweet("Hello, #Devoxx 2014!");

Slide 68

Slide 68 text

public class TwitterApplication implements Runnable {
 private final Tweeter tweeter;
 private final Timeline timeline; @Inject
 public TwitterApplication(Tweeter tweeter, Timeline timeline) {
 this.tweeter = tweeter; this.timeline = timeline;} @Override public void run() { tweeter.tweet("Hello #Devoxx 2014!”); timeline.loadMore(20);
 for (Tweet tweet : timeline.get()) { System.out.println(tweet); } } }

Slide 69

Slide 69 text

@Singleton @Component(modules = { NetworkModule.class,
 TwitterModule.class,
 !})
 public interface TwitterComponent { TwitterApplication app(); }

Slide 70

Slide 70 text

@Singleton @Component(modules = { NetworkModule.class,
 TwitterModule.class,
 !})
 public interface TwitterComponent { TwitterApplication app(); } TwitterComponent component = DaggerTwitterComponent.builder() .twitterModule(newTwitterModule(“JakeWharton")) .build(); component.app().run();

Slide 71

Slide 71 text

public class TwitterApplication implements Runnable {
 @Inject Tweeter tweeter;
 @Inject Timeline timeline; @Inject
 public TwitterApplication(Tweeter tweeter, Timeline timeline) {
 this.tweeter = tweeter; this.timeline = timeline;} @Override public void run() { tweeter.tweet("Hello #Devoxx 2014!”); timeline.loadMore(20);
 for (Tweet tweet : timeline.get()) { System.out.println(tweet); } } }

Slide 72

Slide 72 text

@Singleton @Component(modules = { NetworkModule.class,
 TwitterModule.class,
 !})
 public interface TwitterComponent { void injectApp(TwitterApplication app); }

Slide 73

Slide 73 text

@Singleton @Component(modules = { NetworkModule.class,
 TwitterModule.class,
 !})
 public interface TwitterComponent { void injectApp(TwitterApplication app); } TwitterComponent component = DaggerTwitterComponent.builder() .twitterModule(newTwitterModule(“JakeWharton")) .build(); TwitterApplication app = new TwitterApplication();
 component.injectApp(app); app.run();

Slide 74

Slide 74 text

@Singleton @Component(modules = { NetworkModule.class,
 TwitterModule.class,
 !})
 public interface TwitterComponent { void injectActivity(TwitterActivity activity); } TwitterComponent component = DaggerTwitterComponent.builder() .twitterModule(newTwitterModule(“JakeWharton")) .build(); TwitterActivity activity = // Android creates instance...
 component.injectActivity(activity); // use tweet and timeline in activity…

Slide 75

Slide 75 text

Components • Modules 與 injections 之間的橋樑,讓兩者能互 通 • Component 為 injector,實際發⽣生 inject 的⼈人 • Scope 的概念

Slide 76

Slide 76 text

@Component( dependencies = ApiComponent.class, modules = TwitterModule.class
 ) public interface TwitterComponent {
 void injectActivity(TwitterActivity activity); } @Singleton
 @Component(modules = NetworkModule.class) public interface ApiComponent { 
 }

Slide 77

Slide 77 text

@Singleton
 @Component(modules = NetworkModule.class) public interface ApiComponent { TwitterApi api();
 } @Component( dependencies = ApiComponent.class, modules = TwitterModule.class
 ) public interface TwitterComponent {
 void injectActivity(TwitterActivity activity); }

Slide 78

Slide 78 text

@Module
 public class TwitterModule { private final String user; public TwitterModule(String user) {
 this.user = user; } @Provides @Singleton Tweeter provideTweeter(TwitterApi api) { return new Tweeter(api, user); } @Provides @Singleton Timeline provideTimeline(TwitterApi api) { return new Tweeter(api, user); } }

Slide 79

Slide 79 text

ApiComponent apiComponent = Dagger_ApiComponent.create(); TwitterComponent twitterComponent = DaggerTwitterComponent.builder() .apiComponent(apiComponent) .twitterModule(new TwitterModule("JakeWharton"))
 .build(); TwitterActivity activity = // Android creates instance...
 component.injectActivity(activity);

Slide 80

Slide 80 text

Scope Annotations • Only create a single instance. • @Singleton 是最⼤大的 scope
 (可以想像是最上層的 scope) • ⾃自定 scope,可以讓程式更清楚,也可以有較短 的 lifecycle @Scope public @interface User {
 }

Slide 81

Slide 81 text

@Module
 public class TwitterModule { private final String user; public TwitterModule(String user) {
 this.user = user; } @Provides Tweeter provideTweeter(TwitterApi api) { return new Tweeter(api, user); } @Provides Timeline provideTimeline(TwitterApi api) { return new Tweeter(api, user); } }

Slide 82

Slide 82 text

@Module
 public class TwitterModule { private final String user; public TwitterModule(String user) {
 this.user = user; } @Provides @User Tweeter provideTweeter(TwitterApi api) { return new Tweeter(api, user); } @Provides @User Timeline provideTimeline(TwitterApi api) { return new Tweeter(api, user); } }

Slide 83

Slide 83 text

@Component( dependencies = ApiComponent.class, modules = TwitterModule.class
 ) public interface TwitterComponent {
 void injectActivity(TwitterActivity activity); }

Slide 84

Slide 84 text

@User @Component( dependencies = ApiComponent.class, modules = TwitterModule.class
 ) public interface TwitterComponent {
 void injectActivity(TwitterActivity activity); }

Slide 85

Slide 85 text

No content

Slide 86

Slide 86 text

No content

Slide 87

Slide 87 text

No content

Slide 88

Slide 88 text

No content

Slide 89

Slide 89 text

No content

Slide 90

Slide 90 text

No content

Slide 91

Slide 91 text

No content

Slide 92

Slide 92 text

No content

Slide 93

Slide 93 text

No content

Slide 94

Slide 94 text

No content

Slide 95

Slide 95 text

No content

Slide 96

Slide 96 text

Dagger 1 public abstract class ObjectGraph {
 public static ObjectGraph create(Object... modules) {}
 public abstract ObjectGraph plus(Object... modules);
 public abstract void validate();
 public abstract void injectStatics();
 public abstract T get(Class type);
 public abstract T inject(T instance); } public @interface Module {
 Class[] injects() default { };
 Class[] staticInjections() default { };
 Class[] includes() default { };
 Class addsTo() default Void.class;
 boolean overrides() default false;
 boolean complete() default true;
 boolean library() default true; } public @interface Provides {
 enum Type { UNIQUE, SET }
 Type type() default Type.UNIQUE; } public interface Lazy {
 T get(); } public interface MembersInjector {
 void injectMembers(T instance); }

Slide 97

Slide 97 text

Dagger 2 public @interface Component {
 Class[] modules() default {}; Class[] dependencies()default {};
 } public @interface Module { Class[] includes() default {}; } public @interface Provides { } public @interface MapKey { boolean unwrapValue(); } public interface Lazy { T get();
 }

Slide 98

Slide 98 text

Issues • Gained 13% of processor performance at google scale • No reflection at all • Less flexible

Slide 99

Slide 99 text

Demo https://github.com/ch8908/djdemo

Slide 100

Slide 100 text

Reference • DAGGER 2 - A New Type of dependency injection
 https://www.youtube.com/watch?v=oK_XtfXPkqw • Dependency Injection with Dagger 2
 https://speakerdeck.com/jakewharton/ dependency-injection-with-dagger-2-devoxx-2014 • The Future of Dependency Injection with Dagger 2
 https://www.parleys.com/tutorial/ 5471cdd1e4b065ebcfa1d557/