Date post: | 18-Aug-2015 |
Category: |
Software |
Upload: | mailrugroup |
View: | 210 times |
Download: | 0 times |
{
Dagger2: dependency injection in Android
Vladimir Tagakov
Hollywood Principle
Не звоните нам, мы сами вам перезвоним.
Hollywood Principle
Это паттерн проектирования, а не библиотека.
В каждом проекте используется DI
Dependency Injection
Tweeter Tiwtter API
Network Client
Dependency Injection
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 = //...
client.newCall(request).execute(); }}
public class TwitterApi {private final OkHttpClient client =
new OkHttpClient();
public void postTweet(String user, String tweet) { Request request = //... client.newCall(request).execute();
}}
public class TwitterApi {private final OkHttpClient client =
new OkHttpClient();
public void postTweet(String user, String tweet) { Request request = //... client.newCall(request).execute();
}}
public class TwitterApi {private final OkHttpClient client;public TwitterApi(OkHttpClient client) {
this.client = client;}
public void postTweet(String user, String tweet) { Request request = //... client.newCall(request).execute();
}}
public class Tweeter { public void tweet(String tweet) { TwitterApi api = new TwitterApi();
api.postTweet("JakeWharton", tweet);}
}
public class Tweeter { public void tweet(String tweet) { TwitterApi api = new TwitterApi(
new OkHttpClient() );api.postTweet("JakeWharton", tweet);
}}
public class Tweeter { public void tweet(String tweet) { TwitterApi api = new TwitterApi(
new OkHttpClient() );api.postTweet("JakeWharton", tweet);
}}
public class Tweeter { private final TwitterApi api = new TwitterApi(new OkHttpClient());
public void tweet(String tweet) {api.postTweet("JakeWharton", tweet);
}}
public class Tweeter { private final TwitterApi api = new TwitterApi(new OkHttpClient());
public void tweet(String tweet) {api.postTweet("JakeWharton", tweet);
}}
public class Tweeter { private final TwitterApi api = new TwitterApi(new OkHttpClient());
public Tweeter(String user) { this.user = user;}
public void tweet(String tweet) {api.postTweet(user, tweet);
}}
Tweeter tweeter = new Tweeter("JakeWharton");tweeter.tweet("Hello!");
Tweeter tweeter = new Tweeter("JakeWharton");tweeter.tweet("Hello!");
Timeline timeline = new Timeline("JakeWharton");timeline.loadMore(20);for (Tweet tweet : timeline.get()) {
System.out.println(tweet);}
public class Timeline {private final List<Tweet> cache =
new ArrayList<>();private final TwitterApi api =
new TwitterApi(new OkHttpClient()); private final String user;
public Timeline(String user) { this.user = user; }
public List<Tweet> get() { /* ... */ } public void loadMore(int amount) { /* ... */ }}
public class Timeline {private final List<Tweet> cache =
new ArrayList<>();private final TwitterApi api;
private final String user;
public Timeline(TwitterApi api, String user) {this.user = user;
this.api = api; }
public List<Tweet> get() { /* ... */ } public void loadMore(int amount) { /* ... */ }}
public class Timeline {private final List<Tweet> cache =
new ArrayList<>();private final TwitterApi api;
private final String user;
public Timeline(TwitterApi api, String user) {this.user = user;
this.api = api; }
public List<Tweet> get() { /* ... */ } public void loadMore(int amount) { /* ... */ }}
public class Tweeter { private final TwitterApi api = new TwitterApi(new OkHttpClient());
public Tweeter(String user) { this.user = user;}
public void tweet(String tweet) {api.postTweet(user, tweet);
}}
public class Tweeter { private final TwitterApi api;
public Tweeter(TwitterApi api, String user) {this.user = user;
this.api = api; }
public void tweet(String tweet) {api.postTweet(user, tweet);
}}
public class Tweeter { private final TwitterApi api;
public Tweeter(TwitterApi api, String user) {this.user = user;
this.api = api; }
public void tweet(String tweet) {api.postTweet(user, tweet);
}}
Tweeter tweeter = new Tweeter("JakeWharton");tweeter.tweet("Hello!");
Timeline timeline = new Timeline("JakeWharton");timeline.loadMore(20);for (Tweet tweet : timeline.get()) {
System.out.println(tweet);}
OkHttpClient client = new OkHttpClient();TwitterApi api = new TwitterApi(client);String user = "Jake Wharton"; Tweeter tweeter = new Tweeter(api, user);tweeter.tweet("Hello!"); Timeline timeline = new Timeline(api, user);timeline.loadMore(20);for (Tweet tweet : timeline.get()) {
System.out.println(tweet);}
OkHttpClient client = new OkHttpClient();TwitterApi api = new TwitterApi(client);String user = "Jake Wharton"; Tweeter tweeter = new Tweeter(api, user);tweeter.tweet("Hello!"); Timeline timeline = new Timeline(api, user);timeline.loadMore(20);for (Tweet tweet : timeline.get()) {System.out.println(tweet);}
Tweeter Tiwtter API
Network Client
Dependency Injection
Twitter App• Timeline• Tweeter
Tiwtter API Network Client
Dependency Injection
OkHttpClient client = new OkHttpClient();TwitterApi api = new TwitterApi(client);String user = "Jake Wharton"; Tweeter tweeter = new Tweeter(api, user);tweeter.tweet("Hello!"); Timeline timeline = new Timeline(api, user);timeline.loadMore(20);for (Tweet tweet : timeline.get()) {System.out.println(tweet);}
Как избежать этого?
Guice Dagger (v1)
Немного истории
Граф объектов проверяется в рантайме Большое количество рефлексии Медленная инициализация
Guice
Использование FQCN в качестве ключей при хранении элементов графа
Использование рефлексии
Dagger (v1)
Разработан Java Core Libraries Team Compile time анализ графа
зависимостей Отсутствие рефлексии Совместимость с ProGuard
Dagger v2
@Module + @Provides: для удовлетворения зависимтостей
@Inject: для запроса зависимостей @Component: соединяет все это вместе
Dagger API
Модули – классы аннотированные @Module, содержащие методы аннотированные @Provides
Удовлетворение зависимостей
public class NetworkModule { OkHttpClient provideOkHttpClient() { return
new OkHttpClient();}
TwitterApi provideTwitterApi(OkHttpClient client) {return new TwitterApi(client); }}
@Modulepublic class NetworkModule { @Provides
OkHttpClient provideOkHttpClient() { return new OkHttpClient();
}
@ProvidesTwitterApi provideTwitterApi(OkHttpClient client) {return new TwitterApi(client); }}
@Modulepublic class NetworkModule { @Provides @Singleton OkHttpClient provideOkHttpClient() { return new OkHttpClient();
}
@Provides @SingletonTwitterApi provideTwitterApi(OkHttpClient client) {return new TwitterApi(client); }}
Удовлетворение зависимостей
OkHttpClient NetworkModule#provideOkHttpClient
TwitterApi NetworkModule#provideTwitterApi
Удовлетворение зависимостей
OkHttpClient NetworkModule#provideOkHttpClient
TwitterApi NetworkModule#provideTwitterApi
Tweeter NetworkModule#provideTweeter
Timeline NetworkModule#provideTimeline
Injection в конструктор Injection в поле Injection в метод
Типы injection
@Inject на единственном конструкторе Параметры конструктора –
зависимости Зависимости можно хранить в
приватных переменных Неявно делает класс доступным для
последующего инжекта
Injection в конструктор
public class TwitterApplication { private final Tweeter tweeter; private final Timeline timeline;
@Inject public TwitterApplication(Tweeter tweeter, Timeline timeline) {
this.tweeter = tweeter; this.timeline = timeline;
} // ... }
@Modulepublic class NetworkModule { @Provides @Singleton OkHttpClient provideOkHttpClient() { return new OkHttpClient();
}
@Provides @SingletonTwitterApi provideTwitterApi(OkHttpClient client) {return new TwitterApi(client); }}
public class TwitterApi {private final OkHttpClient client;@Injectpublic TwitterApi(OkHttpClient client) {
this.client = client;}
public void postTweet(String user, String tweet) { Request request = //... client.newCall(request).execute();
}}
@Singleton public class TwitterApi {
private final OkHttpClient client;@Injectpublic TwitterApi(OkHttpClient client) {
this.client = client;}
public void postTweet(String user, String tweet) { Request request = //... client.newCall(request).execute();
}}
@Inject над каждой зависимостью Поля не могут быть private или final Объект ответственен за процесс
инжекта
Единственный способ инъектить зависимости в объекты созданием которых управляем не мы
Injection в поле
public class TwitterActivity extends Activity { @Inject Tweeter tweeter;
@Inject Timeline timeline; // ...}
Мост между модулями и получателями зависимостей
Инжектор
Components
@Singleton@Component(modules = { NetworkModule.class,TwitterModule.class,})public interface TwitterComponent {
Tweeter tweeter();void inject(TwitterActivity activity);
}
public class TwitterActivity extends Activity { @Inject Tweeter tweeter;
@Inject Timeline timeline; public void onCreate(Bundle savedInstanceState) {
Dagger_TwitterComponent.builder()
.build().inject(this);}
// ...}
Linked.in/in/tagakov
Вопросы?