본문

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

공유

댓글