100
Android with Dagger 2 千碩 / Kros iOS/Android Developer

Android with dagger_2

  • Upload
    -

  • View
    835

  • Download
    1

Embed Size (px)

Citation preview

Page 1: Android with dagger_2

Android with Dagger 2⿈黃千碩 / Kros

iOS/Android Developer

Page 2: Android with dagger_2

Dependency Injection

• 中⽂文 - 相依性注⼊入?

• No “new”, dependencies come to you.

Page 3: Android with dagger_2

Dependency Injection

• ⼀一種 Design Pattern

• 最快速,且不⽤用任何 Liberary 即可達成

• 其實每個 app 中都已經有實作 DJ

Page 4: Android with dagger_2

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

Page 5: Android with dagger_2

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

Page 6: Android with dagger_2

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

Page 7: Android with dagger_2

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

Page 8: Android with dagger_2

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

Page 9: Android with dagger_2

Libraries

• Spring

• Guice

• Dagger (v1)

• PicoContainer

• CDI

Page 10: Android with dagger_2

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.

Page 11: Android with dagger_2

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.

Page 12: Android with dagger_2

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.

Page 13: Android with dagger_2

Dagger API• @Module + @Provides: 提供相依性的機制

• @Inject: 要求提供相依性

• @Component: modules 與 injections 之間的橋樑,讓兩者能互通

• 另外有⼀一些語法糖可以使⽤用,使⽤用起來更⽅方便

• 被設計成可以拆成許多⼩小元件,並組合起來使⽤用

Page 14: Android with dagger_2

Providing Dependencies

• Modules 是⼀一些 classes,⽽而這些 classes 中的 methods 提供相依性。

• 必須在 class 上加上 @Module

• 必須在每個 method 上加上 @Provides

Page 15: Android with dagger_2

public class NetworkModule {

OkHttpClient provideOkHttpClient() { return new OkHttpClient(); }

TwitterApi provideTwitterApi(OkHttpClient client) { return new TwitterApi(client); }}

Page 16: Android with dagger_2

@Module public class NetworkModule {

OkHttpClient provideOkHttpClient() { return new OkHttpClient(); }

TwitterApi provideTwitterApi(OkHttpClient client) { return new TwitterApi(client); }}

Page 17: Android with dagger_2

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

@Provides TwitterApi provideTwitterApi(OkHttpClient client) { return new TwitterApi(client); }}

Page 18: Android with dagger_2

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

@Provides @Singleton TwitterApi provideTwitterApi(OkHttpClient client) { return new TwitterApi(client); }}

Page 19: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Page 20: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Page 21: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Page 22: Android with dagger_2

Providing Dependencies

• Modules 是⼀一些 classes,⽽而這些 classes 中的 methods 提供相依性。

• 必須在 class 上加上 @Module

• 必須在每個 method 上加上 @Provides

• Modules 可以拆開成很多 module,也可以組合在⼀一起使⽤用

Page 23: Android with dagger_2

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

Page 24: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Tweeter

Timeline

Page 25: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 26: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 27: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 28: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 29: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 30: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 31: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 32: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 33: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 34: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 35: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 36: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 37: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 38: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 39: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 40: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 41: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 42: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 43: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 44: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Tweeter

Timeline

Page 45: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 46: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Tweeter

Timeline

Page 47: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 48: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 49: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Tweeter

Timeline

Page 50: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 51: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 52: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Tweeter

Timeline

Page 53: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

Tweeter

Timeline

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Page 54: Android with dagger_2

OkHttpClient

Providing Dependencies

NetworkModule#provideOkHttpClient

TwitterApi NetworkModule#provideTwitterApi

TwitterModule#provideTweeter

TwitterModule#provideTimeline

Tweeter

Timeline

Page 55: Android with dagger_2

Requesting Dependencies

• 必須要有 @Inject 的 annotation

• 有三種 inject ⽅方式

• Constructor, field, and method injection.

Page 56: Android with dagger_2

Constructor Injection

• 在 Constructor 加上 @Inject

• 表⽰示 Constructor 的參數需要 dependency

• 這些參數可以被使⽤用在 private 或 final fields.

Page 57: Android with dagger_2

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

Page 58: Android with dagger_2

Method Injection

• 在 methods 上加上 @Inject

• 表⽰示 method 的參數需要 dependency

• Injection 發⽣生在物件被完全建⽴立之後

• 只有⼀一個合理的 use case: passing ‘this’ to a dependency.

Page 59: Android with dagger_2

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

Page 60: Android with dagger_2

Field Injection

• 在 fields 上加上 @Inject

• Field 不能為 private 或是 final

• Injection 發⽣生在物件被完全建⽴立之後

• 在 android 中最常⾒見到

Page 61: Android with dagger_2

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

Page 62: Android with dagger_2

Components

• Modules 與 injections 之間的橋樑,讓兩者能互通

• Component 為 injector,實際發⽣生 inject 的⼈人

• Scope 的概念

Page 63: Android with dagger_2

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

Page 64: Android with dagger_2

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

Page 65: Android with dagger_2

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

Page 66: Android with dagger_2

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

@Modulepublic class TwitterModule { private final String user;

public TwitterModule(String user) { this.user = user; } // …

Page 67: Android with dagger_2

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

Tweeter tweeter = component.tweeter(); tweeter.tweet("Hello, #Devoxx 2014!");

Page 68: Android with dagger_2

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

Page 69: Android with dagger_2

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

Page 70: Android with dagger_2

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

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

component.app().run();

Page 71: Android with dagger_2

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

Page 72: Android with dagger_2

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

Page 73: Android with dagger_2

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

Page 74: Android with dagger_2

@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…

Page 75: Android with dagger_2

Components

• Modules 與 injections 之間的橋樑,讓兩者能互通

• Component 為 injector,實際發⽣生 inject 的⼈人

• Scope 的概念

Page 76: Android with dagger_2

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

@Singleton@Component(modules = NetworkModule.class)public interface ApiComponent { }

Page 77: Android with dagger_2

@Singleton@Component(modules = NetworkModule.class)public interface ApiComponent { TwitterApi api();}

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

Page 78: Android with dagger_2

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

Page 79: Android with dagger_2

ApiComponent apiComponent = Dagger_ApiComponent.create();

TwitterComponent twitterComponent = DaggerTwitterComponent.builder() .apiComponent(apiComponent).twitterModule(new TwitterModule("JakeWharton")).build();

TwitterActivity activity = // Android creates instance...component.injectActivity(activity);

Page 80: Android with dagger_2

Scope Annotations

• Only create a single instance.

• @Singleton 是最⼤大的 scope (可以想像是最上層的 scope)

• ⾃自定 scope,可以讓程式更清楚,也可以有較短的 lifecycle

@Scopepublic @interface User {}

Page 81: Android with dagger_2

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

Page 82: Android with dagger_2

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

Page 83: Android with dagger_2

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

Page 84: Android with dagger_2

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

Page 85: Android with dagger_2
Page 86: Android with dagger_2
Page 87: Android with dagger_2
Page 88: Android with dagger_2
Page 89: Android with dagger_2
Page 90: Android with dagger_2
Page 91: Android with dagger_2
Page 92: Android with dagger_2
Page 93: Android with dagger_2
Page 94: Android with dagger_2
Page 95: Android with dagger_2
Page 96: Android with dagger_2

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> T get(Class<T> type); public abstract <T> 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> { T get();}public interface MembersInjector<T> { void injectMembers(T instance);}

Page 97: Android with dagger_2

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> { T get(); }

Page 98: Android with dagger_2

Issues

• Gained 13% of processor performance at google scale

• No reflection at all

• Less flexible

Page 99: Android with dagger_2

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

Page 100: Android with dagger_2

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/