Dagger 2'de, özellikle de kapsamlı grafiklerin yaşam döngüsünde kafamı kapsamları etrafına sarmaya çalışıyorum. Kapsamdan çıktığınızda temizlenecek bir bileşeni nasıl oluşturursunuz?
Bir Android uygulaması söz konusu olduğunda, Dagger 1.x kullanıldığında, genellikle uygulama düzeyinde, etkinlik düzeyinde bir alt kapsam oluşturmak için genişleteceğiniz bir kök kapsamınız olur.
public class MyActivity {
private ObjectGraph mGraph;
public void onCreate() {
mGraph = ((MyApp) getApplicationContext())
.getObjectGraph()
.plus(new ActivityModule())
.inject(this);
}
public void onDestroy() {
mGraph = null;
}
}
Alt kapsam, bir referans tuttuğunuz sürece mevcuttu, bu durumda Aktivitenizin yaşam döngüsü budur. Referansın onDestroy'a bırakılması, kapsamlı grafiğin çöp toplama işleminin serbest olmasını sağladı.
DÜZENLE
Jesse Wilson kısa süre önce bir mea culpa yayınladı
Dagger 1.0, kapsam adlarını kötü bir şekilde mahvetti ... @Singleton ek açıklaması hem kök grafikler hem de özel grafikler için kullanılır, bu nedenle bir şeyin gerçek kapsamının ne olduğunu anlamak zordur.
ve okuduğum / duyduğum diğer her şey, kapsamların çalışma şeklini iyileştiren Dagger 2'ye doğru işaret ediyor, ancak farkı anlamakta zorlanıyorum. @Kirill Boyarshinov'un aşağıdaki yorumuna göre, bir bileşenin yaşam döngüsü veya bağımlılık her zamanki gibi somut referanslarla belirleniyor. Öyleyse, Dagger 1.x ve 2.0 kapsamları arasındaki fark, tamamen anlamsal bir açıklık meselesi mi?
Benim anlayışım
Hançer 1.x
Bağımlılıklar ya @Singleton
da değildi. Bu, kök grafik ve alt grafiklerdeki bağımlılıklar için de aynı derecede geçerliydi ve bağımlılığın hangi grafiğe bağlı olduğu konusunda belirsizliğe yol açtı (bkz . inşa edildi mi? )
Hançer 2.0
Özel kapsamlar, anlamsal olarak net kapsamlar oluşturmanıza izin verir, ancak işlevsel @Singleton
olarak Dagger 1.x'te uygulamaya eşdeğerdir .
// 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;
}
}
Paket , kullanımın bu bileşenin yaşam döngüsü ile ilgili niyetinizi@PerActivity
iletmesidir , ancak nihayetinde bileşeni her yerde / her zaman kullanabilirsiniz. Dagger'ın tek sözü, belirli bir bileşen için, kapsam açıklamalı yöntemlerin tek bir örnek döndürecektir. Ayrıca, Dagger 2'nin, modüllerin yalnızca aynı kapsamda olan veya kapsam dışı bağımlılıkları sağladığını doğrulamak için bileşendeki kapsam açıklamasını kullandığını varsayıyorum.
Özetle
Bağımlılıklar hala tekildir veya tekil değildir, ancak @Singleton
artık uygulama düzeyinde tekli örnekler için tasarlanmıştır ve özel kapsamlar, daha kısa bir yaşam döngüsüyle tekli bağımlılıklara açıklama eklemek için tercih edilen yöntemdir.
Geliştirici, artık gerekli olmayan referansları atarak bileşenlerin / bağımlılıkların yaşam döngüsünü yönetmekten sorumludur ve bileşenlerin amaçlandıkları kapsamda yalnızca bir kez oluşturulmasını sağlamaktan sorumludur, ancak özel kapsam ek açıklamaları bu kapsamın tanımlanmasını kolaylaştırır. .
64.000 Dolarlık Soru *
Dagger 2 kapsamları ve yaşam döngüleri hakkındaki anlayışım doğru mu?
* Aslında 64.000 dolarlık bir soru değil.
plus()
, yeni grafiğe referans kullanılarak Activity'de saklanıyordu ve yaşam döngüsüne bağlıydı (referansı kaldırıldıonDestroy
). Kapsamlara gelince, bileşen uygulamalarınızın derleme zamanında hatasız ve her bağımlılık karşılanarak üretilmesini sağlarlar. Yani sadece dokümantasyon amaçlı değil. Bu konudan bazı örneklere göz atın .