Bağımlılık Enjeksiyonuna Giriş Bağımlılık Enjeksiyonu (DI), bağımlılıkları oluşturma ve yönetme kontrolünün uygulamadan harici bir varlığa aktarıldığı Kontrolün Tersine Çevrilmesi'ni (IoC) uygulamak için kullanılan bir tasarım desenidir. Bu, daha modüler, test edilebilir ve sürdürülebilir kod oluşturmaya yardımcı olur. Nesneleri oluşturma sorumluluğunun kodun diğer bölümlerine aktarıldığı bir tekniktir. Bu, gevşek bağlantıyı teşvik ederek kodu daha modüler ve yönetilmesi daha kolay hale getirir. Sınıfların düzgün çalışması için sıklıkla diğer sınıflara referanslara ihtiyacı vardır. Örneğin, sınıfı gerektiren bir sınıfını düşünün. Bu gerekli sınıflar bağımlılıklar olarak bilinir. sınıfının çalışması için sınıfının bir örneğine sahip olması gerekir. Book Library Library Book Bir sınıfın ihtiyaç duyduğu nesneleri elde etmesinin üç temel yolu vardır: : Sınıf kendi bağımlılıklarını oluşturur ve başlatır. Örneğin, sınıfı sınıfının kendi örneğini oluşturur ve başlatır. Kendi kendini yapılandırma Library Book : Sınıf, bağımlılıkları harici bir kaynaktan alır. getters ve gibi bazı Android API'leri bu şekilde çalışır. Harici alma Context getSystemService() : Bağımlılıklar, sınıfa, ya inşa edildiğinde ya da bunları gerektiren yöntemler aracılığıyla sağlanır. Örneğin, kurucusu bir örneğini parametre olarak alır. Bağımlılık Enjeksiyonu Library Book Üçüncü seçenek bağımlılık enjeksiyonudur! DI ile, sınıf örneğinin bunları kendisi edinmesi yerine, sınıfın bağımlılıklarını siz sağlarsınız. Bağımlılık Enjeksiyonu Olmadan Örnek DI olmadan, kendi bağımlılığını oluşturan bir şu şekilde görünebilir: Book Library class Library { private Book book = new Book(); void open() { book.read(); } } public class Main { public static void main(String[] args) { Library library = new Library(); library.open(); } } Bu bir DI örneği değildir çünkü sınıfı kendi oluşturur. Bu sorunlu olabilir çünkü: Library Book : ve sıkı bir şekilde bağlıdır. örneği bir tür kullanır ve bu da alt sınıfların veya alternatif uygulamaların kullanılmasını zorlaştırır. Sıkı bağlantı Library Book Library Book : olan sert bağımlılık, testi daha zorlu hale getirir. gerçek bir örneğini kullanır ve farklı test durumları için değiştirmek için test kopyalarının kullanılmasını önler. Test zorlukları Book Library Book Book Bağımlılık Enjeksiyonu ile Örnek DI ile, her örneği kendi nesnesini oluşturmak yerine, kurucusunda bir nesnesini parametre olarak alır: Library Book Book class Library { private Book book; Library(Book book) { this.book = book; } void open() { book.read(); } } public class Main { public static void main(String[] args) { Book book = new Book(); Library library = new Library(book); library.open(); } Ana işlev kullanır. , bağlı olduğundan, uygulama bir örneğini oluşturur ve ardından bunu bir örneğini oluşturmak için kullanır. Bu DI tabanlı yaklaşımın faydaları şunlardır: Library Library Book Book Library : farklı uygulamalarını geçirebilirsiniz. Örneğin, kullanmasını istediğiniz adında yeni bir alt sınıfını tanımlayabilirsiniz. DI ile, bir örneğini geçirmeniz yeterlidir ve başka bir değişiklik yapmadan çalışır. Library Yeniden Kullanılabilirliği Book Library Library Book EBook EBook Library : Farklı senaryoları test etmek için test kopyalarını gönderebilirsiniz. Library Kolay Test Edilmesi Başka bir DI Örneği Bir sınıfının bir sınıfına dayandığı bir senaryoyu düşünün. DI olmadan, doğrudan bir örneği oluşturur ve bu da farklı bildirim türlerini kullanmayı veya hizmeti çeşitli bildirim uygulamalarıyla test etmeyi zorlaştırır. NotificationService Notification NotificationService Notification DI'ı açıklamak için bu örneği yeniden düzenleyelim: interface Notification { void send(); } class EmailNotification implements Notification { @Override public void send() { // Send email notification } } class SMSNotification implements Notification { @Override public void send() { // Send SMS notification } } class NotificationService { void sendNotification(Notification notification) { notification.send(); } } Artık belirli bir sınıftan ziyade arayüzüne bağlıdır. Bu, farklı uygulamalarının birbirinin yerine kullanılabilmesine olanak tanır. Kullanmak istediğiniz uygulamayı yöntemi aracılığıyla ayarlayabilirsiniz: NotificationService Notification Notification sendNotification NotificationService service = new NotificationService(); service.sendNotification(new EmailNotification()); service.sendNotification(new SMSNotification()); Android'de Bağımlılık Enjeksiyon Yöntemleri DI’nin üç ana türü vardır: : Bağımlılıklar, sınıfın bir arayüz veya başka bir sınıf aracılığıyla erişebileceği yöntemler aracılığıyla geçirilir. Önceki örnek yöntem enjeksiyonunu göstermektedir. Yöntem (Arayüz) Enjeksiyonu : Bağımlılıklar sınıfa, kendi constructor'ı aracılığıyla geçirilir. Constructor Enjeksiyonu class NotificationService { private final Notification notification; public NotificationService(Notification notification) { this.notification = notification; } public void sendNotification() { notification.send(); } } public class Main { public static void main(String[] args) { NotificationService service = new NotificationService(new EmailNotification()); service.sendNotification(); } } : Aktiviteler ve parçalar gibi belirli Android çerçeve sınıfları sistem tarafından örneklendirilir, bu nedenle oluşturucu enjeksiyonu mümkün değildir. Alan enjeksiyonuyla, bağımlılıklar sınıf oluşturulduktan sonra örneklendirilir. 3. Alan Enjeksiyonu (veya Ayarlayıcı Enjeksiyonu) class NotificationService { private Notification notification; public Notification getNotification() { return notification; } public void setNotification(Notification notification) { this.notification = notification; } public void sendNotification() { notification.send(); } } public class Main { public static void main(String[] args) { NotificationService service = new NotificationService(); service.setNotification(new EmailNotification()); service.sendNotification(); } } : Bağımlılıklar, çoğunlukla notasyonu kullanılarak metotlar aracılığıyla sağlanır. 4. Metot Enjeksiyonu @Inject Bağımlılık Enjeksiyonunun Avantajları Sınıflar daha yeniden kullanılabilir hale gelir ve belirli uygulamalara daha az bağımlı hale gelir. Bu, sınıfların artık bağımlılıklarını yönetmediği ancak sağlanan herhangi bir yapılandırmayla çalıştığı kontrolün tersine çevrilmesinden kaynaklanır. Bağımlılıklar API yüzeyinin bir parçasıdır ve nesne oluşturma veya derleme zamanında doğrulanabilir, bu da yeniden düzenlemeyi kolaylaştırır. Bir sınıf bağımlılıklarını yönetmediğinden, çeşitli senaryoları kapsayacak şekilde test sırasında farklı uygulamalar geçirilebilir. Otomatik Bağımlılık Enjeksiyonu Önceki örnekte, bir kütüphane kullanmadan farklı sınıfların bağımlılıklarını manuel olarak oluşturdunuz, sağladınız ve yönettiniz. Bu yaklaşıma manuel bağımlılık enjeksiyonu denir. Basit durumlar için işe yarasa da, bağımlılık ve sınıf sayısı arttıkça zahmetli hale gelir. Manuel bağımlılık enjeksiyonunun birkaç dezavantajı vardır: : Büyük uygulamalar için, tüm bağımlılıkları yönetmek ve bunları doğru şekilde bağlamak çok fazla tekrarlayan koda neden olabilir. Çok katmanlı bir mimaride, en üst katman için bir nesne oluşturmak, altındaki katmanlar için tüm bağımlılıkları sağlamayı gerektirir. Örneğin, bir bilgisayar oluşturmak için bir CPU, bir anakart, RAM ve diğer bileşenlere ihtiyacınız vardır; ve bir CPU'nun transistörlere ve kapasitörlere ihtiyacı olabilir. Kalıp Kod : Uygulamanızda tembel başlatmalar veya nesneleri belirli akışlara göre kapsamlandırma gibi önceden bağımlılıklar oluşturamadığınızda, bağımlılıklarınızın bellekteki yaşam sürelerini yönetmek için özel bir kapsayıcı (veya bağımlılık grafiği) yazmanız ve sürdürmeniz gerekir. Karmaşık Bağımlılık Yönetimi Kütüphaneler sizin için bağımlılıklar oluşturarak ve sağlayarak bu süreci otomatikleştirebilir. Bu kütüphaneler iki kategoriye ayrılır: : Bunlar bağımlılıkları çalışma zamanında birbirine bağlar. Yansıma Tabanlı Çözümler : Bunlar derleme zamanında bağımlılıkları bağlamak için kod üretir. Statik Çözümler Dagger, Google tarafından yönetilen Java, Kotlin ve Android için popüler bir bağımlılık enjeksiyon kütüphanesidir. Dagger, sizin için bağımlılık grafiğini oluşturarak ve yöneterek uygulamanızdaki DI'ı basitleştirir. Guice gibi yansıma tabanlı çözümlerle ilişkili birçok geliştirme ve performans sorununu ele alan tamamen statik, derleme zamanı bağımlılıkları sağlar. Yansımaya Dayalı Çözümler Bu çerçeveler bağımlılıkları çalışma zamanında birbirine bağlar: : Bağımlılıkları bağlamak için yansımayı kullanan bir çalışma zamanı DI çerçevesi. Hafif ve hızlı olacak şekilde tasarlanmıştır, bu da onu Android uygulamaları için uygun hale getirir. Toothpick Statik Çözümler Bu çerçeveler, derleme zamanında bağımlılıkları bağlamak için kod üretir: : Dagger'ın üzerine inşa edilen Hilt, Dagger bağımlılık enjeksiyonunu bir Android uygulamasına dahil etmenin standart bir yolunu sağlar. . Hilt Önceden tanımlanmış bileşenler ve kapsamlar sağlayarak Dagger'ın kurulumunu ve kullanımını basitleştirir : Kotlin için hafif ve basit bir DI framework'ü. Koin, bağımlılıkları tanımlamak için bir DSL kullanır ve kurulumu ve kullanımı kolaydır. Koin : Kullanımı ve anlaşılması kolay Kotlin tabanlı bir DI framework'üdür. Bağımlılıkları yönetmek için basit ve esnek bir API sağlar. Kodein Bağımlılık Enjeksiyonuna Alternatifler Bağımlılık enjeksiyonuna bir alternatif, servis konum belirleyici örüntüsüdür. Bu tasarım örüntüsünün ayrıca sınıfları somut bağımlılıklarından ayırmaya yardımcı olur. Bağımlılıkları oluşturan ve depolayan, bunları talep üzerine sağlayan servis konum belirleyici olarak bilinen bir sınıf yaratırsınız. object ServiceLocator { fun getProcessor(): Processor = Processor() } class Computer { private val processor = ServiceLocator.getProcessor() fun start() { processor.run() } } fun main(args: Array<String>) { val computer = Computer() computer.start() } Hizmet konum belirleme kalıbı, bağımlılıkların nasıl tüketildiği konusunda bağımlılık enjeksiyonundan farklıdır. Hizmet konum belirleme kalıbıyla, sınıflar ihtiyaç duydukları bağımlılıkları ister; bağımlılık enjeksiyonuyla, uygulama gerekli nesneleri proaktif olarak sağlar. Dagger 2 Nedir? Dagger 2, Android için popüler bir DI çerçevesidir. Derleme zamanı kod üretimi kullanır ve yüksek performansıyla bilinir. Dagger 2, bağımlılıkları işlemek için gerekli kodu üreterek bağımlılık enjeksiyonu sürecini basitleştirir, kalıpları azaltır ve verimliliği artırır. Dagger 2, Android'de bağımlılık enjeksiyonu için açıklama tabanlı bir kütüphanedir. İşte temel açıklamalar ve amaçları: : Bağımlılıklar sağlayan sınıfları tanımlamak için kullanılır. Örneğin, bir modül Retrofit için bir sağlayabilir. @Module ApiClient : Bir modüldeki yöntemleri, bağımlılıkların nasıl oluşturulacağını ve döndürüleceğini belirtmek için açıklar. @Provides : Bağımlılıkları istemek için kullanılır. Alanlara, oluşturuculara ve yöntemlere uygulanabilir. @Inject : ve arasında köprü kuran bir arayüz. Tüm modülleri içerir ve uygulama için oluşturucu sağlar. @Component @Module @Inject : Bağımlılığın tek bir örneğinin oluşturulmasını sağlar. @Singleton : Soyut sınıflarda bağımlılıkları sağlamak için kullanılır, benzer ancak daha özdür. @Binds @Provides Hançer Bileşenleri Dagger, projeniz için bir bağımlılık grafiği üretebilir ve bu sayede ihtiyaç duyulduğunda bağımlılıkların nereden alınacağını belirleyebilir. Bunu etkinleştirmek için bir arayüz oluşturmanız ve onu ile açıklamanız gerekir. @Component arayüzünde, ihtiyaç duyduğunuz sınıfların örneklerini döndüren yöntemleri tanımlarsınız (örneğin, ). açıklaması, Dagger'a ifşa ettiği türleri karşılamak için gereken tüm bağımlılıkları içeren bir kapsayıcı oluşturmasını söyler. Bu kapsayıcı bir Dagger bileşeni olarak bilinir ve Dagger'ın bağımlılıklarıyla birlikte nasıl sağlayacağını bildiği nesnelerin bir grafiğini içerir. @Component BookRepository @Component Örnek içeren bir örneği ele alalım: LibraryRepository : Dagger'ın örneğini nasıl oluşturacağını bilmesi için oluşturucusuna bir açıklaması ekleyin. Oluşturucuyu Açıklama LibraryRepository LibraryRepository @Inject public class LibraryRepository { private final LocalLibraryDataSource localDataSource; private final RemoteLibraryDataSource remoteDataSource; @Inject public LibraryRepository(LocalLibraryDataSource localDataSource, RemoteLibraryDataSource remoteDataSource) { this.localDataSource = localDataSource; this.remoteDataSource = remoteDataSource; } } : Benzer şekilde, bağımlılıkların ( ve ) oluşturucularını da açıklama ekleyerek Dagger'ın bunları nasıl oluşturacağını bilmesini sağlayın. 2. Bağımlılıkları Açıklama LocalLibraryDataSource RemoteLibraryDataSource public class LocalLibraryDataSource { @Inject public LocalLibraryDataSource() { // Initialization code } } public class RemoteLibraryDataSource { private final LibraryService libraryService; @Inject public RemoteLibraryDataSource(LibraryService libraryService) { this.libraryService = libraryService; } } : Bağımlılık grafiğini tanımlamak için ile açıklamalı bir arayüz oluşturun. 3. Bileşeni Tanımlayın @Component @Component public interface ApplicationComponent { LibraryRepository getLibraryRepository(); } Projeyi derlediğinizde Dagger sizin için arayüzünün bir uygulamasını üretir, genellikle olarak adlandırılır. ApplicationComponent DaggerApplicationComponent Kullanım Artık oluşturulan bileşeni, bağımlılıkları otomatik olarak eklenen sınıflarınızın örneklerini elde etmek için kullanabilirsiniz: public class MainApplication extends Application { private ApplicationComponent applicationComponent; @Override public void onCreate() { super.onCreate(); applicationComponent = DaggerApplicationComponent.create(); } public ApplicationComponent getApplicationComponent() { return applicationComponent; } } Etkinliğinizde veya parçanızda örneğini alabilirsiniz: LibraryRepository public class MainActivity extends AppCompatActivity { @Inject LibraryRepository libraryRepository; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ((MainApplication) getApplication()).getApplicationComponent().inject(this); // Use the injected libraryRepository } } Dagger 2'deki Temel Kavramlar 1. Modüller ∘ Modüllerin Temel Kavramları ∘ Bileşenlere Modüller Dahil Etme 2. Kapsamlar 3. Bileşenler 4. Bileşen Bağımlılıkları 5. Çalışma Zamanı Bağlamaları 1. Modüller Dagger 2'deki modüller, bileşenlere bağımlılıklar sağlayan ile açıklanan sınıflardır. Bağımlılıkların nasıl oluşturulacağını ve sağlanacağını belirtmek için veya ile açıklanan yöntemler içerirler. Modüller, uygulamanızın ihtiyaç duyduğu nesnelerin oluşturulmasını organize etmek ve yönetmek için önemlidir. @Module @Provides @Binds Modüllerin Temel Kavramları @Module Açıklaması: Bu açıklama, bir sınıfı Dagger modülü olarak tanımlamak için kullanılır. Bir modül sınıfı, bağımlılıklar sağlayan yöntemler içerir. @Provides Annotation: Bu açıklama, bir modül içindeki yöntemlerde, yöntemin belirli bir bağımlılığı sağladığını belirtmek için kullanılır. Bu yöntemler, bağımlılıkların örneklerini oluşturmaktan ve döndürmekten sorumludur. @Binds Açıklaması: Bu açıklama, soyut sınıflarda bir uygulamayı bir arayüze bağlamak için kullanılır. Provides'tan daha özlüdür ve modül soyut bir sınıf olduğunda kullanılır. @Provides Bir Modül Örneği @Module public class NetworkModule { @Provides @Singleton Retrofit provideRetrofit() { return new Retrofit.Builder() .baseUrl("https://api.example.com") .addConverterFactory(GsonConverterFactory.create()) .build(); } @Provides @Singleton OkHttpClient provideOkHttpClient() { return new OkHttpClient.Builder() .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)) .build(); } } Bu örnekte, ile açıklanan bir sınıftır. ve örneklerini oluşturan ve döndüren ile açıklanan iki yöntem içerir. NetworkModule @Module Retrofit OkHttpClient @Provides @Binds Kullanımı Bir arayüz ve uygulaması olduğunda, uygulamayı arayüze bağlamak için kullanabilirsiniz. Bu, kullanmaktan daha özlüdür. @Binds @Provides public interface ApiService { void fetchData(); } public class ApiServiceImpl implements ApiService { @Override public void fetchData() { // Implementation } } @Module public abstract class ApiModule { @Binds abstract ApiService bindApiService(ApiServiceImpl apiServiceImpl); } Bu örnekte, ile açıklanan soyut bir sınıftır. yöntemi bağlamak için ile açıklanmıştır. ApiModule @Module bindApiService ApiServiceImpl ApiService @Binds Modüller sağladıkları işlevselliğe göre düzenlenebilir. Örneğin, ağ işlemleri, veritabanı işlemleri ve kullanıcı arayüzüyle ilgili bağımlılıklar için ayrı modülleriniz olabilir. Örnek: : ve gibi ağ ile ilgili bağımlılıkları sağlar. NetworkModule Retrofit OkHttpClient : gibi veritabanıyla ilgili bağımlılıkları sağlar. DatabaseModule RoomDatabase : ve gibi UI ile ilgili bağımlılıkları sağlar. UIModule ViewModel Presenter Bileşenlere Modülleri Dahil Etme Modüller, ihtiyaç duyan sınıflara bağımlılıklar sağlamak için bileşenlere dahil edilir. İşte nasıl kurabileceğiniz: UygulamaBileşeni.java: @Singleton @Component(modules = {NetworkModule.class, DatabaseModule.class}) public interface ApplicationComponent { void inject(MyApplication application); } Bu örnekte , uygulamaya bağımlılıklar sağlamak için ve içerir. ApplicationComponent NetworkModule DatabaseModule 2. Kapsamlar Dagger 2'deki kapsamlar, bağımlılıkların yaşam döngüsünü tanımlayan açıklamalardır. Tek bir bağımlılık örneğinin belirli bir kapsam içinde oluşturulmasını ve paylaşılmasını sağlarlar. Bu, belleğin verimli bir şekilde yönetilmesine ve bağımlılıkların uygun yerlerde yeniden kullanılmasının sağlanmasına yardımcı olur. : Uygulamanın yaşam döngüsü boyunca tek bir bağımlılık örneğinin olmasını sağlar. Tekil Kapsam : Bir etkinliğin yaşam döngüsü içerisinde tek bir bağımlılık örneğinin olmasını sağlar. Etkinlik Kapsamı : Bir parçanın yaşam döngüsü içerisinde tek bir bağımlılık örneğinin olmasını sağlar. Parça Kapsamı 1. Tekil Kapsam : kapsamı, bir bağımlılığın tek bir örneğinin oluşturulmasını ve uygulamanın tüm yaşam döngüsü boyunca paylaşılmasını sağlar. Tanım @Singleton Bu kapsam genellikle ağ istemcileri, veritabanı örnekleri veya paylaşılan tercihler gibi tüm uygulama genelinde paylaşılması gereken bağımlılıklar için kullanılır. Örnek: @Singleton @Component(modules = {NetworkModule.class, DatabaseModule.class}) public interface ApplicationComponent { void inject(MyApplication application); } Bu örnekte ek açıklaması, ve tarafından sağlanan ve örneklerinin tekil olmasını ve tüm uygulama genelinde paylaşılmasını sağlar. @Singleton NetworkModule DatabaseModule Retrofit Database 2. Faaliyet Kapsamı : (özel kapsam), bir bağımlılığın tek bir örneğinin bir aktivitenin yaşam döngüsü içerisinde oluşturulmasını ve paylaşılmasını sağlar. Tanım @ActivityScope Bu kapsam, bir etkinliğe özgü olan ve etkinlik her yeniden oluşturulduğunda yeniden oluşturulması gereken sunucular veya görünüm modelleri gibi bağımlılıklar için yararlıdır. : Örnek @Scope @Retention(RetentionPolicy.RUNTIME) public @interface ActivityScope { } @ActivityScope @Component(dependencies = ApplicationComponent.class, modules = ActivityModule.class) public interface ActivityComponent { void inject(MainActivity mainActivity); } Bu örnekte, açıklaması, tarafından sağlanan bağımlılıkların etkinliğin yaşam döngüsüne göre kapsamlandırılmasını sağlar. @ActivityScope ActivityModule 3. Parça Kapsamı : (başka bir özel kapsam), bir bağımlılığın tek bir örneğinin bir parçanın yaşam döngüsü içinde oluşturulmasını ve paylaşılmasını sağlar. Tanım @FragmentScope Kullanım Durumu: Bu kapsam, parçaya özgü olan ve parça her yeniden oluşturulduğunda yeniden oluşturulması gereken bağımlılıklar (parçaya özgü sunucular veya görünüm modelleri gibi) için yararlıdır. : Örnek @Scope @Retention(RetentionPolicy.RUNTIME) public @interface FragmentScope { } @FragmentScope @Component(dependencies = ActivityComponent.class, modules = FragmentModule.class) public interface FragmentComponent { void inject(MyFragment myFragment); } Bu örnekte, açıklaması, tarafından sağlanan bağımlılıkların parçanın yaşam döngüsüne göre kapsamlandırılmasını sağlar. @FragmentScope FragmentModule 3. Bileşenler Bileşen bağımlılıkları, bir bileşenin diğerine bağımlı olmasını sağlayarak bağımlılıkların yeniden kullanılmasını sağlar. İki ana bileşen bağımlılığı türü vardır: : Uygulamanın tamamında ihtiyaç duyulan bağımlılıkları sağlar. Uygulama Bileşeni : Belirli bir etkinlik içinde ihtiyaç duyulan bağımlılıkları sağlar. Etkinlik Bileşeni 1. Uygulama Bileşeni : Uygulama Bileşeni, tüm uygulama boyunca ihtiyaç duyulan bağımlılıkları sağlar. Genellikle, bağımlılıkların uygulama genelinde paylaşıldığından emin olmak için ile kapsamlandırılır. Tanım @Singleton Bu bileşen, ağ istemcileri, veritabanı örnekleri veya paylaşılan tercihler gibi küresel olarak kullanılabilir olması gereken bağımlılıklar için kullanılır. : Örnek @Singleton @Component(modules = {NetworkModule.class, DatabaseModule.class}) public interface ApplicationComponent { void inject(MyApplication application); } Bu örnekte , tüm uygulama genelinde paylaşılan ve örneklerini sağlamaktan sorumludur. ApplicationComponent Retrofit Database 2. Etkinlik Bileşeni : Etkinlik Bileşeni, belirli bir etkinlik içinde ihtiyaç duyulan bağımlılıkları sağlar. Genellikle, etkinlik her yeniden oluşturulduğunda bağımlılıkların yeniden oluşturulmasını sağlamak için gibi özel bir kapsamla kapsamlandırılır. Tanım @ActivityScope Bu bileşen, sunucular veya görünüm modelleri gibi bir etkinliğe özgü bağımlılıklar için kullanılır. : Örnek @ActivityScope @Component(dependencies = ApplicationComponent.class, modules = ActivityModule.class) public interface ActivityComponent { void inject(MainActivity mainActivity); } Bu örnekte , bağımlıdır ve özgü bağımlılıklar sağlar. ActivityComponent ApplicationComponent MainActivity 4. Bileşen Bağımlılıkları Bileşen bağımlılıkları, bir bileşenin diğerine bağımlı olmasını sağlayarak bağımlılıkların yeniden kullanılmasını sağlar. İki ana bileşen bağımlılığı türü vardır: : Bir alt bileşen, başka bir bileşenin çocuğudur ve üst bileşeninin bağımlılıklarına erişebilir. Alt Bileşenler : Bu, bir bileşenin alt bileşen olmadan başka bir bileşene bağımlı olmasını sağlar. Bağımlılık Niteliği 1. Alt bileşenler: Bir alt bileşen, başka bir bileşenin çocuğudur ve üst bileşeninin bağımlılıklarına erişebilir. Alt bileşenler üst bileşen içinde tanımlanır ve kapsamını devralabilir. : Örnek @ActivityScope @Subcomponent(modules = ActivityModule.class) public interface ActivitySubcomponent { void inject(MainActivity mainActivity); } Bu örnekte , ana bileşenin bir alt bileşenidir ve onun bağımlılıklarına erişebilir. ActivitySubcomponent 2. Bağımlılık Niteliği Bu, bir bileşenin alt bileşen olmadan başka bir bileşene bağımlı olmasını sağlar. Bağımlı bileşen, ana bileşen tarafından sağlanan bağımlılıklara erişebilir. : Örnek @ActivityScope @Component(dependencies = ApplicationComponent.class, modules = ActivityModule.class) public interface ActivityComponent { void inject(MainActivity mainActivity); } Bu örnekte , bağımlıdır ve onun bağımlılıklarına erişebilir. ActivityComponent ApplicationComponent 5. Çalışma Zamanı Bağlamaları Dagger 2'deki çalışma zamanı bağlamaları, ihtiyaç duyuldukları bağlama göre çalışma zamanında oluşturulan ve yönetilen bağımlılıkların sağlanması anlamına gelir. : Uygulama süresince yaşaması gereken bağımlılıklar için kullanılır. Uygulama Bağlamı : Bir etkinlik kadar uzun süre yaşaması gereken bağımlılıklar için kullanılır. Etkinlik Bağlamı 1. Uygulama Bağlamı : Uygulama bağlamı, tüm uygulamanın yaşam döngüsüne bağlı bir bağlamdır. Uygulamanın kendisi kadar uzun süre yaşaması gereken bağımlılıklar için kullanılır. Tanım Tüm uygulama genelinde paylaşılan ve her etkinlik veya parça için yeniden oluşturulması gerekmeyen bağımlılıklar. Örnekler arasında ağ istemcileri, veritabanı örnekleri ve paylaşılan tercihler bulunur. : Örnek @Module public class AppModule { private final Application application; public AppModule(Application application) { this.application = application; } @Provides @Singleton Application provideApplication() { return application; } @Provides @Singleton Context provideApplicationContext() { return application.getApplicationContext(); } } Bu örnekte, uygulama bağlamını tekil bir bağımlılık olarak sağlar. yöntemi, sağlanan bağlamın uygulamanın yaşam döngüsüne bağlı olduğundan emin olur. AppModule provideApplicationContext 2. Etkinlik Bağlamı : Etkinlik bağlamı, belirli bir etkinliğin yaşam döngüsüne bağlı bir bağlamdır. Etkinliğin kendisi kadar uzun süre yaşaması gereken bağımlılıklar için kullanılır. Tanım Bir aktiviteye özgü olan ve aktivite her yeniden oluşturulduğunda yeniden oluşturulması gereken bağımlılıklar. Örnekler arasında görünüm modelleri, sunucular ve kullanıcı arayüzüyle ilgili bağımlılıklar bulunur. : Örnek @Module public class ActivityModule { private final Activity activity; public ActivityModule(Activity activity) { this.activity = activity; } @Provides @ActivityScope Activity provideActivity() { return activity; } @Provides @ActivityScope Context provideActivityContext() { return activity; } } Bu örnekte, etkinlik bağlamını kapsamlı bir bağımlılık olarak sağlar. yöntemi, sağlanan bağlamın etkinliğin yaşam döngüsüne bağlı olduğundan emin olur. ActivityModule provideActivityContext Bileşenlerde Çalışma Zamanı Bağlamalarını Kullanma Bu çalışma zamanı bağlamalarını kullanmak için bileşenlerinize ilgili modülleri eklemeniz gerekir: : Uygulama Bileşeni @Singleton @Component(modules = {AppModule.class, NetworkModule.class}) public interface ApplicationComponent { void inject(MyApplication application); Context getApplicationContext(); } : Etkinlik Bileşeni @ActivityScope @Component(dependencies = ApplicationComponent.class, modules = ActivityModule.class) public interface ActivityComponent { void inject(MainActivity mainActivity); Context getActivityContext(); } Bağlamları Enjekte Etmek Bileşenlerinizi ve modüllerinizi kurduktan sonra, ihtiyaç duyduğunuzda bağlamları sınıflarınıza ekleyebilirsiniz. : Bir Aktivitede Örnek public class MainActivity extends AppCompatActivity { @Inject Context activityContext; @Inject Context applicationContext; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ApplicationComponent appComponent = ((MyApplication) getApplication()).getApplicationComponent(); ActivityComponent activityComponent = DaggerActivityComponent.builder() .applicationComponent(appComponent) .activityModule(new ActivityModule(this)) .build(); activityComponent.inject(this); // Use the injected contexts Log.d("MainActivity", "Activity Context: " + activityContext); Log.d("MainActivity", "Application Context: " + applicationContext); } } Bu örnekte, hem etkinlik bağlamını hem de uygulama bağlamını bağımlılık enjeksiyonu yoluyla alır. Bu, etkinliğin bağımlılıkların belirli ihtiyaçlarına göre uygun bağlamı kullanmasına olanak tanır. MainActivity Örnek: Android Uygulamasında Dagger 2 Kullanımı Dagger 2 Kurulumu Dagger 2'yi projenizde kullanmak için dosyanıza aşağıdaki bağımlılıkları eklemeniz gerekiyor: build.gradle dependencies { implementation 'com.google.dagger:dagger:2.x' annotationProcessor 'com.google.dagger:dagger-compiler:2.x' } Dagger 2'nin son sürümüyle değiştirin. 2.x Adım 1: Bir Modül Tanımlayın Bağımlılıkları sağlamak için bir modül oluşturun. Örneğin, örneği sağlamak için bir : Retrofit NetworkModule @Module public class NetworkModule { @Provides @Singleton Retrofit provideRetrofit() { return new Retrofit.Builder() .baseUrl("https://api.example.com") .addConverterFactory(GsonConverterFactory.create()) .build(); } } Adım 2: Bir Bileşeni Tanımlayın Modül ile bağımlılıklara ihtiyaç duyan sınıflar arasında köprü kuracak bir bileşen oluşturun: @Singleton @Component(modules = {NetworkModule.class}) public interface ApplicationComponent { void inject(MyApplication application); } Adım 3: Bağımlılıkları Enjekte Edin Bileşeni, sınıflarınıza bağımlılıklar enjekte etmek için kullanın. Örneğin, sınıfınızda: Application public class MyApplication extends Application { private ApplicationComponent applicationComponent; @Override public void onCreate() { super.onCreate(); applicationComponent = DaggerApplicationComponent.builder() .networkModule(new NetworkModule()) .build(); applicationComponent.inject(this); } public ApplicationComponent getApplicationComponent() { return applicationComponent; } } Adım 4: Enjekte Edilen Bağımlılıkları Kullanın Artık enjekte edilen bağımlılıkları sınıflarınızda kullanabilirsiniz. Örneğin, bir : Activity public class MainActivity extends AppCompatActivity { @Inject Retrofit retrofit; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ((MyApplication) getApplication()).getApplicationComponent().inject(this); // Use the injected Retrofit instance // ... } } Çözüm Konuyu özetleyelim: DI'ın temel amacı, bağımlılıkları yönetmeyi kolaylaştırarak, bağlantıları gevşetmektir. DI kullanarak kod esnekliğini artırabilir ve test sürecini basitleştirebilirsiniz. DI, senaryoya göre farklı uygulamaları olan karmaşık bir konudur. DI'ın farklı dillerde kullanımı, onunla nasıl çalışacağınızı etkileyebilecek özelliklere sahiptir. Dagger 2, bağımlılıkların oluşturulması ve sağlanması sürecini otomatikleştirerek, kalıp kodları azaltır ve sürdürülebilirliği artırır. Dagger 2, uygulama çalıştırılmadan önce tüm bağımlılıkların karşılandığından emin olarak derleme zamanı güvenliği sağlar. Dagger 2, derleme zamanında kod üreterek yansıma tabanlı çözümlerle ilişkili performans yükünden kaçınır.