본문
170608(목) - DI with Dagger2
DI with Dagger2
Dagger API
- @Module + @Provides
mechanism for providing dependencies
- @Inject
mechanism for requesting dependencies
- @Component
bridge between modules and injections
- plus some other sugar, magic, and conventions.
Providing Dependencies
- modules는 methods가 dependencies를 제공하는 class
- @Module on the class.
- @Provides (and friends) on each method.
@Module
public class NetworkModule {
@Provides @Singleton
OkHttpClient prvideOkHttpClient() {
return new OkHttpClient();
}
@Provides @Singleton
TwitterApi provideTwitterApi(OkHttpClient client) {
return new TwitterApi(clent);
}
}
- Designed to be partitioned and composed together.
@Module
public class TwitterModule {
private final String user;
public TwitterModule(String user) {
this.user = user;
}
@Provides @Singleton
Tweeter prvideTweeter(TwitterApi api) {
return new Tweeter(api, user);
}
@Provides @Singleton
Timeline provideTimeline(TwitterApi api) {
return new Timeline(api, user);
}
}
- Tweeter를 시작하는것으로 예를 들면, Tweeter -> TwitterApi -> OkHttpClient 순으로 따라 올라가면서 DI를 요청한다.
- @Provides에서 제공된 객체를 가지고 올라왔던 길을 다시 내려가면서 DI를 진행한다.
- 이미 한번 DI가 진행됐으면 객체가 이미 존재하므로 굳이 최상단까지 올라가지 않더라도 DI 가능.
Requesting Dependencies
- @Inject annotation
- Constructor Injection
- @Inject on a single constructor
- parameters are dependencies
- Dependencies can be stored in private and final fields.
public class TwitterApplication {
private final Tweeter tweeter;
private final Timeline timeline;
@Inject
public TwitterApplication(Tweeter tweeter, Timeline timeline) {
this.tweeter = tweeter;
this.timeline = timeline;
}
...
}
- Implicitly made available for downstream injection.
@Module
public class NetworkModule {
@Provides @Singleton
OkHttpClient prvideOkHttpClient() {
return new OkHttpClient();
}
@Provides @Singleton
TwitterApi provideTwitterApi(OkHttpClient client) {
return new TwitterApi(clent);
}
}
@singleton
public class TwitterApi {
private final OkHttpClient client;
@Inject
public TwitterApi(OkHttpClient client) {
this.client = client;
}
public void postTweet(String user, String tweet) {
OkHttpClient client = new OkHttpClient();
Request request = ...
client.newCall(request).execute();
}
}
- Method Injection
- @Inject on methods
- Method parameters are dependencies
- Injection happens after object is fully instantiated.
- Only one valid use case: passing 'this' to a dependency.
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);
}
}
- Field Injection
- @Inject on fields for dependencies.
- Field may not be private or final.
- Injection happens after object is fully instantiated.
- Object is usually responsible for or aware of injection.
public class TwitterApplication {
@Inject Tweeter tweeter;
@Inject final Timeline timeline;
...
}
Components
- Bridge between modules and injection
- The injector.
@singleton
@Component(modules = {
NetworkModule.class,
TwitterModule.class,
})
public interface TwitterComponent {
Tweeter tweeter();
Timeline timeline();
}
TwitterComponent component = Dagger_TwitterComponent.builder()
.networkModule(new NetworkModule())
.twitterModule(new TwitterModule("신대규"))
.build();
Tweeter tweeter = component.tweeter();
tweeter.tweet("Hello, #Devoxx ~!");
Timeline timeline = component.timeline();
timeline.loadMore(20);
for (Tweet tweet : timeline.get()) {
System.out.println(tweet);
}
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 ~!");
timeline.loadMore(20);
for (Tweet tweet : timeline.get()) {
System.out.println(tweet);
}
}
}
@singleton
@Component(modules = {
NetworkModule.class,
TwitterModule.class,
})
public interface TwitterComponent {
TwitterApplication app();
}
TwitterComponent component = Dagger_TwitterComponent.builder()
.twitterModule(new TwitterModule("신대규"))
.build();
component.app().run();
public class TwitterApplication implements Runnable {
@inject Tweeter tweeter;
@inject Timeline timeline;
@Override
public void run() {
tweeter.tweet("Hello #Devoxx ~!");
timeline.loadMore(20);
for (Tweet tweet : timeline.get()) {
System.out.println(tweet);
}
}
}
@singleton
@Component(modules = {
NetworkModule.class,
TwitterModule.class,
})
public interface TwitterComponent {
void injectApp(TwitterApplication app);
}
TwitterComponent component = Dagger_TwitterComponent.builder()
.twitterModule(new TwitterModule("신대규"))
.build();
TwitterApplication app = new TwitterApplication();
component.injectApp(app);
app.run();
public class TwitterApplication implements Runnable {
@inject Tweeter tweeter;
@inject Timeline timeline;
@Override
public void run() {
tweeter.tweet("Hello #Devoxx ~!");
timeline.loadMore(20);
for (Tweet tweet : timeline.get()) {
System.out.println(tweet);
}
}
}
@singleton
@Component(modules = {
NetworkModule.class,
TwitterModule.class,
})
public interface TwitterComponent {
void injectActivity(TwitterActivity activity);
}
TwitterComponent component = Dagger_TwitterComponent.builder()
.twitterModule(new TwitterModule("신대규"))
.build();
TwitterActivity activity = ...;
component.injectActivity(activity);
public class TwitterApplication implements Runnable {
@inject Tweeter tweeter;
@inject Timeline timeline;
@Override
public void run() {
tweeter.tweet("Hello #Devoxx ~!");
timeline.loadMore(20);
for (Tweet tweet : timeline.get()) {
System.out.println(tweet);
}
}
}
@singleton
@Component(modules = {
NetworkModule.class,
TwitterModule.class,
})
public interface TwitterComponent {
void injectProcessor(Processor processor);
}
TwitterComponent component = Dagger_TwitterComponent.builder()
.twitterModule(new TwitterModule("신대규"))
.build();
TwitterProcessor processor = ...;
component.injectProcessor(processor);
@singleton
@Component(modules = {
NetworkModule.class,
TwitterModule.class,
})
public interface TwitterComponent {
TwitterApplication injectApp(TwitterApplication app);
}
TwitterComponent component = Dagger_TwitterComponent.builder()
.twitterModule(new TwitterModule("신대규"))
.build();
TwitterApplication app = new TwitterApplication();
component.injectApp(app).run();
- Implementation of scopes
- Singleton을 사용하면 component 생성시 create() 만으로도 build 가능
@Singleton
@component(modules = NetworkModule.calss)
public interface ApiComponent {
TwitterApi api();
}
@Singleton
@component(
dependencies = ApiComponent.class,
moduels = TwitterModule.class
}
public interface TwitterComponent {
TwitterApplication app();
}
@Module
public class TwitterModule {
private final String user;
public TwitterModule(String user) {
this.user = user;
}
@Provides @Singleton
Tweeter prvideTweeter(TwitterApi api) {
return new Tweeter(api, user);
}
@Provides @Singleton
Timeline provideTimeline(TwitterApi api) {
return new Timeline(api, user);
}
}
ApiComponent apiComponent = Dagger_ApiComponent.create();
TwitterComponent twitterComponent = Dagger_TwitterComponent.builder()
.apiComponent(apiComponent)
.twitterModule(new TWitterModule("신대규"))
.build();
- Scope Annotations
- Only create a single instance.
- @Singleton is the "largest" scope
- Custom annotations for semantic clarity, shorter lifetime.
@Scope
public @interface User {
}
@Module
public class TwitterModule {
private final String user;
public TwitterModule(String user) {
this.user = user;
}
@Provides @User
Tweeter prvideTweeter(TwitterApi api) {
return new Tweeter(api, user);
}
@Provides @User
Timeline provideTimeline(TwitterApi api) {
return new Timeline(api, user);
}
}
@User
@component(
dependencies = ApiComponent.class,
moduels = TwitterModule.class
}
public interface TwitterComponent {
TwitterApplication app();
}
- Under the Hood
???
'Mobile > DI' 카테고리의 다른 글
170609(금) - DI with Dagger2 (0) | 2017.06.09 |
---|---|
170609(금) - DI with Dagger2 (0) | 2017.06.09 |
170609 (금) - DI with Dagger2 (0) | 2017.06.09 |
170608(목) - DI with Dagger2 (0) | 2017.06.08 |
170608(목) - DI with Dagger2 (0) | 2017.06.08 |
댓글