Android'de bağımlılık ekleme

Bağımlılık yerleştirme (DI), programlamada yaygın olarak kullanılan bir tekniktir. bir uygulamadır. DI ilkelerine uyarak iyi bir uygulama mimarisinin temellerini atabilirsiniz.

Bağımlılık yerleştirmeyi uygulamak, size aşağıdaki avantajları sağlar:

  • Kodun yeniden kullanılabilirliği
  • Yeniden düzenleme kolaylığı
  • Test kolaylığı

Bağımlılık yerleştirmenin temelleri

Özellikle Android'de bağımlılık yerleştirmeyi ele almadan önce bu sayfanın bağımlılık yerleştirmenin işleyiş şekline dair daha genel bir bakış sunduk.

Bağımlılık yerleştirme nedir?

Sınıflar için genellikle diğer sınıflara referanslar gerekir. Örneğin, Car sınıfı bir Engine sınıfına referans gerekebilir. Bu gerekli sınıflar dependencies olarak ayarlanmıştır. Bu örnekte Car sınıfı şuna bağımlıdır: Engine sınıfının bir örneğini burada görebilirsiniz.

Bir sınıf, ihtiyacı olan nesneyi üç şekilde elde edebilir:

  1. Sınıf, ihtiyaç duyduğu bağımlılığı oluşturur. Yukarıdaki örnekte, Car, kendi örneğini oluşturup başlatır Engine.
  2. Başka bir yerden alın. Bazı Android API'leri: Context alıcı ve getSystemService(), bu işi yapın sağlar.
  3. Parametre olarak sağlanmasını sağlayın. Uygulama bunları sağlayabilir bağımlılıkları sınıf oluşturulduğunda veya fonksiyonlara ilettiğinde her bir bağımlılığa ihtiyaç duyanlar için bir fırsat bulunuyor. Yukarıdaki örnekte, Car kurucusu parametre olarak Engine alır.

Üçüncü seçenek bağımlılık eklemedir. Bu yaklaşımla bir sınıfa sahip olmak yerine bağımlılıklarını örneğinin kendisinde olması gerekir.

Bir örnekle açıklayalım. Bağımlılık yerleştirme olmadan, aynı işleve sahip bir Car kodda kendi Engine bağımlılığını oluşturur:

Kotlin

class Car {

    private val engine = Engine()

    fun start() {
        engine.start()
    }
}

fun main(args: Array) {
    val car = Car()
    car.start()
}

Java

class Car {

    private Engine engine = new Engine();

    public void start() {
        engine.start();
    }
}


class MyApp {
    public static void main(String[] args) {
        Car car = new Car();
        car.start();
    }
}
Bağımlılık eklemesiz araba sınıfı

Bu, bir bağımlılık yerleştirme örneği değildir çünkü Car sınıfı kendi Engine projesini oluşturuyor. Bu durum aşağıdaki nedenlerden dolayı sorunlara yol açabilir:

  • Car ve Engine sıkı sıkıya bağlı. Car örneği tek bir kod kullanır ve alt sınıfların veya alternatif uygulamaların kolaycaEngine kullanılır. Car kendi Engine öğesini oluşturacaksa türündeki motorlar için aynı Car öğesini yeniden kullanmak yerine iki tür Car Gas ve Electric.

  • Engine ürününe ciddi düzeyde bağımlılık, testi daha da zorlaştırıyor. Car, bir gerçek bir Engine örneği oluşturur. Bu nedenle, Engine değerini farklı test durumlarında değiştirmek için iki kez test edin.

Bağımlılık yerleştirmede kod nasıl görünür? Her bir örnek yerine başlatma sırasında kendi Engine nesnesini oluşturan Car API'si, Oluşturucuda parametre olarak Engine nesnesi:

Kotlin

class Car(private val engine: Engine) {
    fun start() {
        engine.start()
    }
}

fun main(args: Array) {
    val engine = Engine()
    val car = Car(engine)
    car.start()
}

Java

class Car {

    private final Engine engine;

    public Car(Engine engine) {
        this.engine = engine;
    }

    public void start() {
        engine.start();
    }
}


class MyApp {
    public static void main(String[] args) {
        Engine engine = new Engine();
        Car car = new Car(engine);
        car.start();
    }
}
Bağımlılık ekleme kullanan araba sınıfı

main işlevi, Car değerini kullanır. Car, Engine uygulamasına bağlı olduğundan uygulama Engine örneğini oluşturur ve daha sonra, bunu Car öğesinin bir örneğini oluşturmak için kullanır. İlgili içeriği oluşturmak için kullanılan bu DI tabanlı yaklaşımın avantajları şunlardır:

  • Car ürününün yeniden kullanılabilirliği. Engine öğesinin farklı uygulamalarını Car. Örneğin, Engine adında yeni bir alt sınıf tanımlayabilirsiniz. Car tarafından kullanılmasını istediğiniz ElectricEngine. DI kullanıyorsanız tek yapmanız gereken güncellenen ElectricEngine alt sınıfının bir örneğini iletir, Car hâlâ çalışır başka hiçbir değişiklik yapmadan kullanabilirsiniz.

  • Car için kolay test yapın. Farklı testlerinizi test etmek için testlerinizi senaryoları ele alacağız. Örneğin, Engine değeri için şu adla bir test ikilisi oluşturabilirsiniz: FakeEngine ve farklı testler için yapılandırın.

Android'de bağımlılık yerleştirmenin iki temel yolu vardır:

  • Oluşturucu Yerleştirme. Bu, yukarıda açıklanan şekildedir. Geçerseniz bağımlılıklarını ifade eder.

  • Alan Yerleştirme (veya Setter Yerleştirme). Belirli Android çerçevesi sınıfları öğeler ve parçalar sistem tarafından örneklendirildiğinden, eklemesi mümkün değildir. Alan yerleştirme ile bağımlılıklar örneklendirilir sınıf oluşturulduktan sonra. Kod şöyle görünür:

Kotlin

class Car {
    lateinit var engine: Engine

    fun start() {
        engine.start()
    }
}

fun main(args: Array) {
    val car = Car()
    car.engine = Engine()
    car.start()
}

Java

class Car {

    private Engine engine;

    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    public void start() {
        engine.start();
    }
}

class MyApp {
    public static void main(String[] args) {
        Car car = new Car();
        car.setEngine(new Engine());
        car.start();
    }
}

Otomatik bağımlılık ekleme

Önceki örnekte bağımlılıkları oluşturdunuz, sağladınız ve yönettiniz farklı sınıfları kolayca görebilirsiniz. Buna el ile bağımlılık ekleme veya manuel bağımlılık ekleme. Car içinde Mesela sadece tek bir bağımlılık vardı, ama daha fazla bağımlılık ve sınıf bağımlılıkları manuel olarak eklemeyi daha yorucu hale getirebilir. Manuel bağımlılık ekleme birtakım sorunlar da beraberinde getirir:

  • Büyük uygulamalar için, tüm bağımlılıkları alıp bunları bağlamak büyük miktarda ortak metin kodu gerektirebilir. Çok katmanlı bir üst katman için nesne oluşturmak istiyorsanız öncelikle altındaki katmanların tüm bağımlılıklarını göreceksiniz. Somut bir örnek vermek gerekirse, motor, şanzıman, şasi ve diğer parçalara ihtiyacınız olabilir. Motorda ise silindir ve buji gerekir.

  • Bağımlılıkları aktarmadan önce oluşturamadığınızda gecikmeli başlatmaların veya nesnelerin akışlarının kapsamını belirlemenin, özel bir kapsayıcı (ya da her bir (bağımlılıkların) bellekteki yaşamını yöneten bir kaynaktır.

Süreçleri otomatikleştirerek bu sorunu çözen kütüphaneler var ve bağımlılık sağlamaktan bahsedeceğiz. Bunlar iki kategoriye ayrılır:

  • Çalışma zamanında bağımlılıkları birbirine bağlayan yansıtma tabanlı çözümler.

  • Bağımlılıkları bağlamak için kod oluşturan statik çözümler sırasında görünür.

Dagger, Java için popüler bir bağımlılık ekleme kitaplığıdır. Kotlin ve Google tarafından sağlanan Android. Dagger, DI kullanımını kolaylaştırır bağımlılık grafiğini sizin için oluşturup yöneterek uygulamanızda kullanabilirsiniz. Google birçok bileşeni ele alan tamamen statik ve derleme zamanı bağımlılıkları düşünmeye dayalı çözümlerin geliştirilmesini ve performans Guice.

Bağımlılık yerleştirmenin alternatifleri

Bağımlılık yerleştirmeye alternatif olarak, hizmet bulma aracı ile uyumludur. Hizmet bulma aracı tasarım kalıbı da sınıfların somut bağımlılıklardan ayrıştırılmasını kolaylaştırır. Bir sınıf oluşturursunuz Bağımlılıkları oluşturan ve depolayan hizmet bulucu olarak bilinir, ardından isteğe bağlı olarak bulunduğunu öğrendik.

Kotlin

object ServiceLocator {
    fun getEngine(): Engine = Engine()
}

class Car {
    private val engine = ServiceLocator.getEngine()

    fun start() {
        engine.start()
    }
}

fun main(args: Array) {
    val car = Car()
    car.start()
}

Java

class ServiceLocator {

    private static ServiceLocator instance = null;

    private ServiceLocator() {}

    public static ServiceLocator getInstance() {
        if (instance == null) {
            synchronized(ServiceLocator.class) {
                instance = new ServiceLocator();
            }
        }
        return instance;
    }

    public Engine getEngine() {
        return new Engine();
    }
}

class Car {

    private Engine engine = ServiceLocator.getInstance().getEngine();

    public void start() {
        engine.start();
    }
}

class MyApp {
    public static void main(String[] args) {
        Car car = new Car();
        car.start();
    }
}

Hizmet bulucu kalıbı, özellik açısından bağımlılık eklemesinden farklıdır. emin olun. Hizmet bulucu kalıbında, sınıflar nesnelerin yerleştirilmesini kontrol etme ve isteme; bağımlılık enjeksiyonu ile Uygulama, kontrol özelliğine sahiptir ve gerekli nesneleri proaktif olarak ekler.

Bağımlılık yerleştirme ile karşılaştırıldığında:

  • Bir hizmet bulucunun gerektirdiği bağımlılıkların koleksiyonu, kodu oluşturur tüm testler, aynı global kullanıcı arayüzüyle etkileşim kurması gerektiğinden, test edilmesi daha zordur. hizmet bulma aracı.

  • Bağımlılıklar API yüzeyinde değil, sınıf uygulamasında kodlanır. Sonuç olarak, sınıfın dışarıdan neye ihtiyacı olduğunu bilmek daha zordur. Bunun sonucunda Car veya hizmet bulucuda bulunan bağımlılıklar, çalışma zamanı veya test ile sonuçlanabilir hata mesajları ve referansların başarısız olmasına neden olabilir.

  • Nesnelerin ömürlerini yönetmek, yalnızca nesnel uygulamanın ömründen başka herhangi bir şeye dayanıyor olabilir.

Android uygulamanızda Hilt'i kullanma

Hilt, Jetpack'te öneriliyor uygulama kitaplığını kullanıma sunduk. Hilt, standart bir proje yönetimi yöntemi Uygulamanızdaki her Android sınıfı için kapsayıcılar sağlayarak ve yaşam döngülerini sizin için otomatik olarak yönetmelerine yardımcı olur.

Hilt, popüler DI kitaplığının üzerine inşa edilmiştir Dagger derleme zamanı doğruluğu, çalışma zamanı performansı, ölçeklenebilirlik ve Android Studio desteği sağlamak için tasarlandı.

Hilt hakkında daha fazla bilgi edinmek için Hilt ile Bağımlılık Enjeksiyonu.

Sonuç

Bağımlılık yerleştirme, uygulamanıza aşağıdaki avantajları sağlar:

  • Sınıfların yeniden kullanılabilirliği ve bağımlılıkların ayrıştırılması: Değiştirmek daha kolaydır bağımlılığın uygulamaları. Ters çevirme sayesinde kodun yeniden kullanımı iyileştirildi Sınıflar artık bağımlılıklarının nasıl oluşturulduğunu kontrol edemiyor. herhangi bir yapılandırmayla çalışır.

  • Yeniden düzenleme kolaylığı: Bağımlılıklar, API'nin doğrulanabilir bir parçası haline gelir yüzey, böylece nesne oluşturulma zamanında veya derleme sırasında kontrol edilebilir yerine bu verileri kullanabilirsiniz.

  • Test kolaylığı: Sınıf, bağımlılıklarını yönetmez. Dolayısıyla, test etmek tüm araçları test etmek için farklı uygulamalardan isteyebilirsiniz.

Bağımlılık yerleştirmenin avantajlarını tam olarak anlamak için bu özelliği denemeniz gerekir Manuel bağımlılık ekleme bölümünde gösterildiği gibi uygulamanıza manuel olarak ekleyin.

Ek kaynaklar

Bağımlılık yerleştirme hakkında daha fazla bilgi için aşağıdaki ek kaynakları inceleyin.

Örnekler