Dagger'la ilgili temel bilgiler

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:

  1. @Inject ek açıklamalı bir UserRepository örneği oluşturma kurucusu.

  2. Bağımlılıkları nelerdir?: UserLocalDataSource ve UserRemoteDataSource.

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:

  1. 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 nesnesi LoginUserData.

  2. 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.