Dependency Injection Nedir?

Tuğçe Aras
6 min readJan 14, 2023

--

Selamlar 👋, şimdiki konumuz DI yani Dependency Injection konusu. Ne olduğu, DI için hangi kütüphanelerin kullanıldığı gibi konulara değineceğim. Kütüphane olarak daha çok Hilt üzerinde duracağım. Başlayalım o halde.

Yazımda daha çok DI şeklinde bir kullanım yapacağım. Siz onun Dependency Injection’nın kısaltılmış hali olduğunu unutmayın.

🔹 DI Nedir?

  • İlk önce kelimenin anlamına bakalım.

Dependency(Bağımlılık) -> Bağımlı bir class tarafından kullanılacak olan nesnedir.

Injection -> Nesne bağımlılığını onu kullanacak olan class’a iletmedir.

  • DI, bağımlı olan sınıfı bağımlılıklarından bağımsız hale getiren bir yöntemdir. Yani class’lar arasında bir bağımlılık oluşturmak yerine bu bağımlılıkları dışarıdan ilgili class’lara vererek class’ların bağımsız olmasını sağlamaktır. Anlamadım. Nasıl yani? 🤔 Şöyle ki:
  • Uygulama geliştirirken class’larımız bulunmakta ve bazı class’ların da nesnelerine ihtiyaç duyabilmekteyiz. Nesnelerine ihtiyaç duyduğumuz class’lardan oluşturduğumuz nesneleri kullanmaya başladığımız zaman otomatik olarak o class’a karşı bağımlılıklar oluşmaya başlıyor. (o class’ın fonksiyonunu ya da başka bir özelliğini kullanmak gibi) Dependency Injection’da burada devreye giriyor. Class’ların bağımsız olmasını, birinde yapılan değişikliğin diğerini etkilememesini sağlamaktadır.

DI kullanmanın bizlere ne gibi bir artısı var?

  • Kodun yeniden kullanılabilir olmasını sağlar.
  • Kodun kolayca refactor edilebilmesi.
  • Test yapma kolaylığı.
  • Mimarinin loosely coupled olmasını sağlar.

🔹 DI Türleri

  • DI yapmanın 2 ana yolu vardır. Bunlar:
  1. Constructor Injection: Bağımlılıkları bir class’ın constructor’ı aracılı ile geçirmek için kullanılan DI türüdür.
  2. Field Injection(or Setter Injection): Bağımlılıkların, doğrudan değişkenlerin üzerinde ayarlanması işlemidir.

🔹 DI İçin Kullanılan Kütüphaneler

  • Dagger
  • Hilt
  • Koin
  • RoboGuice
  • ButterKnife
https://i.imgur.com/QtNw9kz.jpg

🔹 Hilt Nedir?

  • Jetpack’in, Android’de dependency injection için önerdiği bir kütüphanedir.
  • Projelerde manuel dependency injection yapmayı azaltan bir kütüphanedir.
  • Initialize işlemlerini otomatik olarak yapmayı sağlamaktadır.
  • Projemizdeki her Activity class’ı için container’lar sağlar ve yaşam döngülerini otomatik olarak yönetir.
  • Dagger üzerine inşa edilmiştir. Dagger’ın sağladığı compile time correctness, runtime performance, scability ve Android Studio desteğinden yararlanmaktadır. Dolayısıyla;

Avantajları:

  • Kolay test edilebilirlik
  • Hızlı kurulum
  • Tekrar kullanılabilen kodlar
  • Kolay refactor edebilme

▶️ Hilt’i Class’ Uygulama

  • @HiltAndroidApp : Hilt’i uygulamamızda kullanacağımızı söylemek ve kendi içerisinde bulunan kodları oluşturmasını sağlamak için kullanılır.

NOT : Oluşturulan Hilt bileşeni Application nesnesinin yaşam döngüsüne eklenerek ona dependency’ler(bağımlılıklar) sağlar.

▶️ Dependency’leri(Bağımlılıkları) Android Class’na Inject Etme

  • @AndroidEntryPoint : Bu annotation’nın koyulduğu class’a aslında şunu demekteyiz. İçinde injection’lar yapılacak haberin olsun.

NOT : Bir Android class’na bu annotation eklendiyse eğer buna bağlı diğer Android class’larına da bu annotation’nı eklememiz gerekir.

▶️ Kullanılan Annotation’lar

  • @Inject : Bu annotation ile bağımlılıkları bağımlı olan class’lara eklemek için kullanırız.

Field Injection:

NOT : Inject yapılan field’lar private olamaz. Private bir field’ı inject etmeye çalışmak derleme hatasına neden olmaktadır.

Constructor Injection:

NOT : @Inject annotation’nını constructor, field ve metotlar ile kullanabilmekteyiz.

  • @Module : Bağımlılıkların/nesnelerin oluşturulduğu sınıfın başına eklenir. @Provides annotation’nı kullanan metotlar içerir.
  • @InstallIn : Modülün hangi Component üzerinde duracağını belirtmek iççin kullandığımız bir annotation’dır.
  • @Provides : Constructor injection yapılamayan bir tip için binding ekler. Dönüş tipi binding tiptedir. Parametreleri bağımlılıklardır. Modüllerde nesneleri bağımlılık olarak tanımlamak için oluşturduğumuz metotlarda kullanılır.
  • @Binds : Bir interface tipini binding etmek için kullanılır. Yani Hilt’e bir interface vermesi gerektiğinde ona hangi implementation’nı kullanacağını söyler. Metotlar modül içerisinde olmalıdır. Bu annotation’nı kullanan metotlar abstract olmalıdır.
  • @Singleton : Bu annotation’nı kullanan bir dependency(bağımlılık) uygulama oturumu boyunca yalnızca bir kez başlatılır. Hep aynı nesneyi bize verir. Tekrar tekrar nesneyi oluşturmaz.

Annotation’lar ile ilgili aşağıdaki cheat sheet’i inceleyebilirsiniz.

developer.android sitesinden alınmıştır

Cheat sheet’in PDF halini indirmek isterseniz : https://developer.android.com/static/images/training/dependency-injection/hilt-annotations.pdf

▶️ Peki bu kadar annotation’dan sonra eğer bir tür (mesela bir interface) birden fazla class tarafından implement edilirse ne olur? ya da yukarıdaki annotation’lardan birini mi kullanmamız gerekir bu durumda? 🤔

  • Karışıklık meydana gelir. Çözüm olarak ise kendi annotation’mızı oluşturarak bu problemi giderebiliriz. Nasıl yani kendi annotation’mızı nasıl oluşturabiliriz ki? 😮

Bunun için 2 annotation bulunmaktadır Bunlar:

  • @Qualifier : Aynı türde birden fazla bağımlılık sağlamak istediğimizde hangisinin kullanılacağına karar vermede kullanılır.
  • @Retentation : Bu annotation, belirli bir annotation’nın ne zaman kullanılacağı ve nasıl atılacağını belirler.

Örnek ile açıklayalım.

@Qualifier ve @Retentation annotation’ların bulunduğu kısma bakarsak eğer orada annotation class şeklinde bir yazım şekli bulunmakta. Aslında annotation class ile biz diyoruz ki benim annoation’larımın ismi “FirstImplement” ve “SecondImplement” olacak diyoruz ve ClassExample içerisinde bunu belirtiyoruz.

Artık FirstImplement annotation’nı gördüğü yerde return olarak bize “First print”, SecondImplemet annotation’nı gördüğü yerde ise “Second print” çıktısı verecektir.

🔹 Hilt’in Desteklediği Android Class’lar

  • Application
  • Activity
  • Fragment
  • View
  • Service
  • Broadcast Receiver

🔹 Android Class’ları İçin Oluşturulan Component’ler

  • Field injection gerçekleştirebileceğimiz her Android Class’ı için @InstallIn annotation’ı ile kullanabileceğimiz bir Hilt bileşeni vardır. Aşağıdaki tabloda bunları görebilmekteyiz.
developer.android sitesinden alınmıştır

NOT : Hilt, Broadcast Receiver ‘ları doğrudan SingletonComponent’ten injection ettiğinden Hilt, broadcast receiver’lar için component oluşturmaz.

🔹 Component Lifetimes

  • Hilt, Android class’ların yaşam döngülerine göre oluşturulan component class’larının örneklerini otomatik olarak oluşturur ve yok eder.
developer.android sitesinden alınmıştır

🔹 Component Scopes

  • Aşağıdaki tabloda Android class’na göre generate edilen component’i ve kullanılan scope’u görmekteyiz.
developer.android sitesinden alınmıştır

🔹 Dagger vs Hilt

  • Structure(Yapısı) : Dagger genel amaçlı bir DI kütüphanesidir. Hilt ise Android için özel olarak tasarlanmıştır. Hilt’te Android için özelleştirilmiş ve optimize edilmiş özellikler bulunmaktadır.
  • Easy of use(Kullanım kolaylığı) : Hilt kullanımının kolay olması özelliğini taşımaktadır. Bunun için önceden tanımlanmış component’leri ve modülleri bulunmaktadır.
  • Performance : Hilt, Dagger’a kıyasla daha performanslıdır. bir üst satırda da belirttiğim gibi Hilt’in daha önceden tanımlanmış modül ve component’leri bulunmaktadır.
  • Testing : Dagger test etme işini daha kolay hale getirmek amacı ile tasarlanmıştır. Hilt ise Dagger’a kıyasla test edilebilirliği daha az esnektir.

🔚 Kısacası

  • DI ile dependency’leri ayrıştırma işlemi kolaylaştı ve class’ların yeniden kullanılabilirliği arttı.
  • Refactoring yapmak kolaylaştı.
  • DI sayesinde nesneler birbirlerine loosely coupled olarak bağlandı yani birbirlerine sıkı sıkı(tightly coupled) bağlı değiller/muhtaç değiller. Bu sayede kod daha esnek ve test edilebilir bir hale gelmiş oldu.
  • DI ile nesneler arasında bağlantıyı anlamak kolaylaştı.
  • DI sayesinde nesneler dinamik olarak configure edilebilir bir duruma geldi.
  • Kod daha anlaşılır, basit ve bakımı kolay hale gelmiş oldu.

Kaynak

https://www.mobiler.dev/post/hilt-ile-dependency-injection

https://medium.com/developer-multicamp/androidde-dependency-injection-f812ab28335e

--

--

Tuğçe Aras
Tuğçe Aras

Written by Tuğçe Aras

Android Developer at Şekerbank T.A.Ş. 💻💚 | https://bio.link/tugcearas

No responses yet