Я намагаюся обернути голову навколо областей в Dagger 2, зокрема, життєвого циклу нанесених графіків. Як створити компонент, який буде очищений, коли ви вийдете з області застосування.
У випадку з додатком для Android, використовуючи Dagger 1.x, у вас зазвичай є коренева область на рівні програми, яку ви розширите, щоб створити дочірнє поле на рівні активності.
public class MyActivity {
private ObjectGraph mGraph;
public void onCreate() {
mGraph = ((MyApp) getApplicationContext())
.getObjectGraph()
.plus(new ActivityModule())
.inject(this);
}
public void onDestroy() {
mGraph = null;
}
}
Дітям сфера існувала до тих пір, поки ви не посилалися на неї, що в цьому випадку було життєвим циклом вашої діяльності. Якщо ввімкнути посилання на onDestroy, гарантія того, що графік, на якому було зафіксовано, можна було збирати сміття
EDIT
Нещодавно Джессі Вілсон опублікував мій випадок
Dagger 1.0 погано розкрутив свої назви областей ... Анотація @Singleton використовується як для кореневих графіків, так і для користувацьких графіків, тому складно розібратися, що таке фактична сфера речей.
і все інше, що я прочитав / почув, вказує на Dagger 2, що покращує спосіб роботи областей, але я намагаюся зрозуміти різницю. Відповідно до коментаря @Kirill Boyarshinov нижче, життєвий цикл компонента або залежності все ще визначається, як зазвичай, конкретними посиланнями. Тож чи різниця між діапазонами Dagger 1.x та 2.0 є суто семантичною ясністю?
Моє розуміння
Кинджал 1.x
Залежності були @Singleton
чи ні. Це однаковою мірою стосувалося залежностей у кореневому графіку та підграфах, що призводило до неоднозначності щодо того, до якого графа залежність залежала (див. У Dagger - синглтони у кешованому під графіку, або вони завжди будуть відтворені, коли новий під графік активності будується? )
Кинджал 2.0
Спеціальні області застосування дозволяють створювати семантично чіткі області застосування, але вони функціонально еквівалентні застосуванню @Singleton
в Dagger 1.x.
// Application level
@Singleton
@Component( modules = MyAppModule.class )
public interface MyAppComponent {
void inject(Application app);
}
@Module
public class MyAppModule {
@Singleton @Named("SingletonScope") @Provides
StringBuilder provideStringBuilderSingletonScope() {
return new StringBuilder("App");
}
}
// Our custom scope
@Scope public @interface PerActivity {}
// Activity level
@PerActivty
@Component(
dependencies = MyAppComponent.class,
modules = MyActivityModule.class
)
public interface MyActivityComponent {
void inject(Activity activity);
}
@Module
public class MyActivityModule {
@PerActivity @Named("ActivityScope") @Provides
StringBuilder provideStringBuilderActivityScope() {
return new StringBuilder("Activity");
}
@Name("Unscoped") @Provides
StringBuilder provideStringBuilderUnscoped() {
return new StringBuilder("Unscoped");
}
}
// Finally, a sample Activity which gets injected
public class MyActivity {
private MyActivityComponent component;
@Inject @Named("AppScope")
StringBuilder appScope
@Inject @Named("ActivityScope")
StringBuilder activityScope1
@Inject @Named("ActivityScope")
StringBuilder activityScope2
@Inject @Named("Unscoped")
StringBuilder unscoped1
@Inject @Named("Unscoped")
StringBuilder unscoped2
public void onCreate() {
component = Dagger_MyActivityComponent.builder()
.myApplicationComponent(App.getComponent())
.build()
.inject(this);
appScope.append(" > Activity")
appScope.build() // output matches "App (> Activity)+"
activityScope1.append("123")
activityScope1.build() // output: "Activity123"
activityScope2.append("456")
activityScope1.build() // output: "Activity123456"
unscoped1.append("123")
unscoped1.build() // output: "Unscoped123"
unscoped2.append("456")
unscoped2.build() // output: "Unscoped456"
}
public void onDestroy() {
component = null;
}
}
Це означає, що при використанні @PerActivity
повідомляється про ваш намір щодо життєвого циклу цього компонента, але в кінцевому підсумку ви можете використовувати його в будь-якому місці та в будь-який час. Єдине обіцянка Дагера полягає в тому, що для даного компонента методи, що коментують область, повернуть один екземпляр. Я також припускаю, що Dagger 2 використовує анотацію про область використання компонента для перевірки того, що модулі забезпечують лише залежності, які знаходяться або в тому самому масштабі, або не входять в рамки.
Підсумок
Залежності як і раніше є однотонними або неоднотонними, але @Singleton
тепер призначені для прикладних одиночних екземплярів на рівні застосунку, а користувацькі сфери є кращим методом для анотування залежностей від однотонних з меншим життєвим циклом.
Розробник несе відповідальність за управління життєвим циклом компонентів / залежностей шляхом викидання посилань, які більше не потрібні, і відповідальних за забезпечення того, щоб компоненти створювалися лише один раз у тій області, для якої вони призначені, але користувацькі анотації щодо сфери полегшують ідентифікацію цієї сфери .
Питання $ 64k *
Чи правильно я розумію сфери дії та життєвий цикл Dagger 2?
* Насправді не питання на $ 64'000.
plus()
посилання на новий графік, зберігався в "Діяльності" і прив'язувався до його "живого циклу" (відмінено вonDestroy
). Що стосується діапазонів, вони гарантують, що ваші компоненти компонентів генеруються без помилок під час компіляції, з задоволенням кожної залежності. Тож це не лише з метою документації. Ознайомтеся з прикладом цієї теми .