Manuel bağımlılık ekleme veya hizmet Android uygulamasındaki yer bulma araçları, cihazınızın boyutuna bağlı olarak belirler. Projenizin ölçeği büyürken karmaşıklığını azaltmak için Bağımlılıkları yönetmek için Dagger'ı kullanın.
Dagger, normalde kullanacağınız kodu taklit eden bir kodu otomatik olarak oluşturur el yazısıyla yazılmıştır. Kod, derleme sırasında oluşturulduğundan izlenebilir. ve görselleştirme gibi yansıtmaya dayalı diğer çözümlere göre Guice.
Dagger kullanmanın avantajları
Dagger, şunları yaparak yorucu ve hataya açık ortak kod yazmanızı engeller:
Manuel olarak oluşturduğunuz
AppContainer
kodunu (uygulama grafiği) oluşturma uygulanmıştır.Uygulama grafiğinde bulunan sınıflar için fabrikalar oluşturma. Bu içsel olarak bağımlılıkların ne kadar karşılandığıdır.
Bir bağımlılığın yeniden kullanılıp kullanılmayacağına veya kapsamların kullanımını değerlendirir.
Sayfadaki giriş akışında yaptığınız gibi belirli akışlar için container'lar önceki bölümü için Dagger alt bileşenlerinden yararlanın. Bu, uygulamanızın artık ihtiyaç duyulmadıklarında nesneleri bellekte serbest bırakarak daha iyi performans elde edebilirsiniz.
Dagger, tüm bunları derleme sırasında otomatik olarak gerçekleştirir. Bunun için bir sınıfın bağımlılıklarını tanımlamış ve bunları kullanarak ek açıklamalar. Dagger, yazacağınız koda benzer bir kod üretiyor manuel olarak ekleyin. Dagger, dahili olarak başvurabileceği nesnelerin bir grafiğini oluşturur bir sınıfın örneğini sağlamanın yolunu bulmak için kullanılır. Grafikteki her sınıf için Dagger, kullandığı fabrika türünde bir sınıf oluşturur iç içe geçmiş olabilir.
Dagger, derleme sırasında kodunuzda adım adım ilerler ve:
Bağımlılık grafikleri oluşturup doğrular; şunları sağlar:
- Her nesnenin bağımlılıkları karşılanabilir, böylece çalışma zamanı yoktur istisnalar olabilir.
- Bağımlılık döngüleri yoktur, bu nedenle de sonsuz döngüler yoktur.
Çalışma zamanında gerçek nesneleri ve bunların bağımlılıklarını oluşturmak için kullanılan sınıfları oluşturur.
Dagger'da basit bir kullanım alanı: Fabrika oluşturma
Dagger ile nasıl çalışabileceğinizi göstermek için
fabrikada gösterilen UserRepository
sınıfı için
şu şemayı kullanın:
UserRepository
öğesini şu şekilde tanımlayın:
Kotlin
class UserRepository( private val localDataSource: UserLocalDataSource, private val remoteDataSource: UserRemoteDataSource ) { ... }
Java
public class UserRepository { private final UserLocalDataSource userLocalDataSource; private final UserRemoteDataSource userRemoteDataSource; public UserRepository(UserLocalDataSource userLocalDataSource, UserRemoteDataSource userRemoteDataSource) { this.userLocalDataSource = userLocalDataSource; this.userRemoteDataSource = userRemoteDataSource; } ... }
Dagger'ın bilmesi için UserRepository
oluşturucuya bir @Inject
ek açıklaması ekleyin
nasıl UserRepository
oluşturulur:
Kotlin
// @Inject lets Dagger know how to create instances of this object class UserRepository @Inject constructor( private val localDataSource: UserLocalDataSource, private val remoteDataSource: UserRemoteDataSource ) { ... }
Java
public class UserRepository { private final UserLocalDataSource userLocalDataSource; private final UserRemoteDataSource userRemoteDataSource; // @Inject lets Dagger know how to create instances of this object @Inject public UserRepository(UserLocalDataSource userLocalDataSource, UserRemoteDataSource userRemoteDataSource) { this.userLocalDataSource = userLocalDataSource; this.userRemoteDataSource = userRemoteDataSource; } }
Yukarıdaki kod snippet'inde Dagger'a şunu söylersiniz:
@Inject
ek açıklamalı birUserRepository
örneği oluşturma kurucusu.Bağımlılıkları nelerdir?:
UserLocalDataSource
veUserRemoteDataSource
.
Dagger artık UserRepository
örneğinin nasıl oluşturulacağını biliyor ancak
ve bağımlılıklarını
nasıl oluşturacağınızı öğrenebilirsiniz. Diğer sınıflara da not eklerseniz
Dagger bunları nasıl oluşturacağını biliyor:
Kotlin
// @Inject lets Dagger know how to create instances of these objects class UserLocalDataSource @Inject constructor() { ... } class UserRemoteDataSource @Inject constructor() { ... }
Java
public class UserLocalDataSource { @Inject public UserLocalDataSource() { } } public class UserRemoteDataSource { @Inject public UserRemoteDataSource() { } }
Hançer bileşenleri
Hançer, projenizdeki bağımlılıkların bir grafiğini oluşturabilir,
ve gerektiğinde bu bağımlılıkları nerede elde edeceğinizi
saptamanız gerekir.
Dagger'ın bunu yapmasını sağlamak için bir arayüz oluşturmanız ve ona
@Component
Dagger, manuel olarak yaptığınız gibi bir container oluşturur
bağımlılık ekleme.
@Component
arayüzünün içinde, geri gelen
örnekleri (ör. UserRepository
). @Component
anlatıyor
çeşitli türleri vardır. Buna Dagger bileşeni denir; içerir
ve Dagger’ın bu işi nasıl yapacağını bildiği nesnelerden oluşan
ve bağımlılıklarını
belirlemenize yardımcı olur.
Kotlin
// @Component makes Dagger create a graph of dependencies @Component interface ApplicationGraph { // The return type of functions inside the component interface is // what can be provided from the container fun repository(): UserRepository }
Java
// @Component makes Dagger create a graph of dependencies @Component public interface ApplicationGraph { // The return type of functions inside the component interface is // what can be consumed from the graph UserRepository userRepository(); }
Siz projeyi derlediğinizde Dagger,
ApplicationGraph
arayüzünün size ait: DaggerApplicationGraph
. ile
ek açıklama işlemcisi olarak Dagger, aşağıdaki öğelerden oluşan bir bağımlılık grafiği
üç sınıf (UserRepository
,
UserLocalDatasource
ve UserRemoteDataSource
):
UserRepository
örneği alınıyor. Bu kodu aşağıdaki şekilde kullanabilirsiniz:
Kotlin
// Create an instance of the application graph val applicationGraph: ApplicationGraph = DaggerApplicationGraph.create() // Grab an instance of UserRepository from the application graph val userRepository: UserRepository = applicationGraph.repository()
Java
// Create an instance of the application graph ApplicationGraph applicationGraph = DaggerApplicationGraph.create(); // Grab an instance of UserRepository from the application graph UserRepository userRepository = applicationGraph.userRepository();
Dagger, her istendiğinde yeni bir UserRepository
örneği oluşturur.
Kotlin
val applicationGraph: ApplicationGraph = DaggerApplicationGraph.create() val userRepository: UserRepository = applicationGraph.repository() val userRepository2: UserRepository = applicationGraph.repository() assert(userRepository != userRepository2)
Java
ApplicationGraph applicationGraph = DaggerApplicationGraph.create(); UserRepository userRepository = applicationGraph.userRepository(); UserRepository userRepository2 = applicationGraph.userRepository(); assert(userRepository != userRepository2)
Bazen bir container'da bağımlılığın benzersiz bir örneğinizin olması gerekir. Bunu birkaç nedenden dolayı isteyebilirsiniz:
Bu türe sahip diğer türlerin, bağımlılık olarak aynı Örneğin, giriş akışında aynı öğe kullanılarak birden fazla
ViewModel
nesnesiLoginUserData
.Bir nesnenin oluşturulması pahalıysa ve yeni bir nesne oluşturmak istemiyorsanız örneğini her bağımlılık olarak bildirdiğinde (ör. JSON ayrıştırıcı) kullanabilirsiniz.
Bu örnekte, benzersiz bir UserRepository
örneğini kullanmak isteyebilirsiniz
Grafikte mevcuttur. Böylece her UserRepository
istediğinizde,
daima aynı örneği alır. Bu, örneğinizde faydalıdır çünkü
daha karmaşık bir uygulama grafiğine sahip farklı bir uygulama
UserRepository
'a bağlı olarak birden fazla ViewModel
nesnesi oluşturuyor ve bu nesneleri
(yeni UserLocalDataSource
ve UserRemoteDataSource
örnekleri oluşturmak için)
UserRepository
sağlanması gerektiği her seferinde.
Manuel bağımlılık eklemede bunu aynı
ViewModel sınıflarının oluşturucularına UserRepository
örneği; ama
çünkü bu kodu manuel olarak yazmadığınız için,
Dagger, aynı örneği kullanmak istediğinizi biliyor. Bu, kapsamla yapılabilir.
ek açıklamaları inceleyin.
Hançer ile Kapsam Oluşturma
Bir nesnenin kullanım ömrünü uzatmak için kapsam ek açıklamalarını kullanabilirsiniz birçok bileşeni vardır. Bu, aynı bağımlılık örneğinin kullanıldığı anlamına gelir. gerektiği zaman kontrol edebilirsiniz.
Depoyu istediğinizde UserRepository
öğesinin benzersiz bir örneğini elde etmek için
ApplicationGraph
öğesinde, @Component
için aynı kapsam ek açıklamasını kullanın
arayüz ve UserRepository
. Etiketleme sırasında @Singleton
Dagger'ın kullandığı javax.inject
paketiyle zaten gelir:
Kotlin
// Scope annotations on a @Component interface informs Dagger that classes annotated // with this annotation (i.e. @Singleton) are bound to the life of the graph and so // the same instance of that type is provided every time the type is requested. @Singleton @Component interface ApplicationGraph { fun repository(): UserRepository } // Scope this class to a component using @Singleton scope (i.e. ApplicationGraph) @Singleton class UserRepository @Inject constructor( private val localDataSource: UserLocalDataSource, private val remoteDataSource: UserRemoteDataSource ) { ... }
Java
// Scope annotations on a @Component interface informs Dagger that classes annotated // with this annotation (i.e. @Singleton) are scoped to the graph and the same // instance of that type is provided every time the type is requested. @Singleton @Component public interface ApplicationGraph { UserRepository userRepository(); } // Scope this class to a component using @Singleton scope (i.e. ApplicationGraph) @Singleton public class UserRepository { private final UserLocalDataSource userLocalDataSource; private final UserRemoteDataSource userRemoteDataSource; @Inject public UserRepository(UserLocalDataSource userLocalDataSource, UserRemoteDataSource userRemoteDataSource) { this.userLocalDataSource = userLocalDataSource; this.userRemoteDataSource = userRemoteDataSource; } }
Alternatif olarak, özel bir kapsam ek açıklaması oluşturup kullanabilirsiniz. Kapsam ek açıklamasını aşağıdaki şekilde oluşturabilirsiniz:
Kotlin
// Creates MyCustomScope @Scope @MustBeDocumented @Retention(value = AnnotationRetention.RUNTIME) annotation class MyCustomScope
Java
// Creates MyCustomScope @Scope @Retention(RetentionPolicy.RUNTIME) public @interface MyCustomScope {}
Ardından, bu şablonu her zamanki gibi kullanabilirsiniz:
Kotlin
@MyCustomScope @Component interface ApplicationGraph { fun repository(): UserRepository } @MyCustomScope class UserRepository @Inject constructor( private val localDataSource: UserLocalDataSource, private val service: UserService ) { ... }
Java
@MyCustomScope @Component public interface ApplicationGraph { UserRepository userRepository(); } @MyCustomScope public class UserRepository { private final UserLocalDataSource userLocalDataSource; private final UserRemoteDataSource userRemoteDataSource; @Inject public UserRepository(UserLocalDataSource userLocalDataSource, UserRemoteDataSource userRemoteDataSource) { this.userLocalDataSource = userLocalDataSource; this.userRemoteDataSource = userRemoteDataSource; } }
Her iki durumda da nesne, öğelere açıklama eklemek için kullanılan aynı kapsamla sağlanır.
@Component
arayüzü. Böylece, bir sonraki gelişinizde
applicationGraph.repository()
,
UserRepository
.
Kotlin
val applicationGraph: ApplicationGraph = DaggerApplicationGraph.create() val userRepository: UserRepository = applicationGraph.repository() val userRepository2: UserRepository = applicationGraph.repository() assert(userRepository == userRepository2)
Java
ApplicationGraph applicationGraph = DaggerApplicationGraph.create(); UserRepository userRepository = applicationGraph.userRepository(); UserRepository userRepository2 = applicationGraph.userRepository(); assert(userRepository == userRepository2)
Sonuç
Dagger'ın avantajları ve nasıl çalıştığına dair temel bilgiler ve tekniklerin kullanılmasıdır.
Sonraki sayfada, Dagger'ı bir Android uygulamasına nasıl ekleyeceğinizi öğreneceksiniz.