Yeni Başlayanlar İçin Dagger 2
Merhaba, genellikle (DI) Dependicies Injection için kullanılan Dagger2 Framework’ünü “Neden kullandığımızı?” , “Nasıl kullandığımızı?” ve “Neyin ne işe yaradığını” bu yazım ile size aktarmaya çalışacağım. Biraz uzun bir yazı olacak ama projelerinizde Dagger 2'yi kullanabilecek bir bilgi seviyeniz olacak.
Eğer daha önce yazdığım MVP, Retrofit, Dagger 2 ve RxJava ile nasıl Android uygulama Geliştirilir adlı yazımı okumadıysanız okumanızı tavsiye ederim.
NOT: Bu yazı serisi, aşağıdaki yazı serisi dikkate alınarak yazılmıştır
Anlatım şeklim şöyle gerçekleşecektir;
- Dependicies Injection’a neden ihtiyacımız var?
- Dagger 2 kullanmadan Dependicies Injection’u kullanmaya çalışacağız.
- Dagger 2 ile manuel yapmaya çalıştığımız Dependicies Injection’u yapmaya çalışacağız.
- Dagger 2 ile basit bir örnek yapmaya çalışacağız.
Neden Dependicies Injection Gibi Bir Yaklaşıma İhtiyacımız Var?
Eğer basit bir proje yapıyor iseniz veya yapmış iseniz çok fazla sınıfınız olmadığı için Dependicies Injection gibi bir kavrama ihtiyacınız olmamıştır. Ama daha büyük projelerde çok fazla sınıfınız olduğu ve bu sınıfların hepsi birbirini kullandığı için bir sınıfa yeni bir özellik eklediğinizde ilgili sınıfı kullanan sınıflar bu özellikten etkilenebiliyor. Veya yeni bir sınıf eklediğiniz zaman ve bu sınıfı başka bir sınıfta kullandığınızda; kullanılan sınıfı kullanan sınıflar bu değişiklikten etkileniyor.
Konuyu anlatırken bile kafanız karıştı değil mi? Birde bunun kodunu yazdığınızı düşünün :)
Bu olayı örneklememiz gerekir ise şu şekilde bir kod parçacığına bakalım;
Bir War nesnesi oluşturmak için 9 satırlık kodda ne kadar fazla nesne oluşturduk. Bu
sadece küçük bir örnek projeniz büyüdükçe içinden çıkılamaz bir hal alacak.
Dagger 2 Sorununuzu Çözmeye Geliyor
Dagger 2 açık kaynaklı DI ( Dependicies Injection ) frameworklerinden biri.
Peki neden bu kadar çok kullanılıyor?
Çünkü, şimdilik Java kodunu taklit eden, izlenebilir bir kaynak kodu oluşturan bir yapıya sahip. Yani Dagger 2 sizin için tüm bağımlılıkları kontrol eder.
“Sözün kısası Dagger 2 olmadan manuel bir şekilde DI yapısı kurmanız, onun peşinden koşmanız gibi olur. Uğraşırsınız ama sonuç almanız çok zor.”
Annotation Nedir?
Annotation(Not) kavramı Java programlama diline JDK 5.0 ile dahil olmuştur. Annotation’lar bir Java programının yapısını değiştirmeyen, sadece yazılan bir program modülü hakkında bilgi veren yapılardır. Genelde yardım amaçlı programcıya hitap eden annotation’lar, 3 farklı yapıda(kaynak kod,derleme anı veya çalışma anı) çalışarak yazılan kodlara dair açıklamalar getirir.
Annotation İşlemleri
Annotation işlemleri compile zamanda sizin için kod oluşturur. Compile süresince oluşturuğu için size performans kaybı yaşatmaz.
Neden Annotation İşlemlerini Bilmeliyim?
Çünkü Dagger 2 Annotation işlemleri üzerinde çalışır. Yani kodunuz compile zamanında oluşur.
Dagger 2 Annotationlarını Öğrenelim
Dagger 2'nin birkaç Annotation’u var onlara ileride bakacağız. Şimdilik Dagger 2'nin önemli olan 2 annotationuna “@Inject” ve “@Component” bakacağız.
@Inject Annotationu
@Inject annotationunu 3 farklı yerde kullanabilirsiniz. Onlar;
- Kurucu metotlarda
- Objelerde
- Metotlarda
Yani @Inject annotationu başka bir deyişle bağımlı olana tüm bağımlılıkları aktarmaya yarar.
@Component Annotationu
Bu annotation herşeyi birbirine bağlayan yapıyı kurmak için kullanılır. Yani @Component annotationuna sahip olan sınıfta hangi sınıfların bağımlılıkları alacağını tanımlarız. Yani bir nevi @Module (ileride göreceğiz) ile @Inject ile köprü görevi görüyor.
Çok konuştuk artık bir kullanalım şu Dagger 2'yi
Dagger 2'yi yukarıda oluşturduğumuz “BattleOfBastards” için kullanacağız. Bu sayede aradaki farka bakabiliriz.
War objesinin “Starks” ve “Boltons” objeclerine bağımlılığı var. Şimdi Dagger 2 ile War objesini tekrar oluşturalım.
@Inject Annotation Kullanımı
Planımız “Starks” ve “Boltons” sınıflarını “War” sınıfı içine inject etmek. Yani Dagger 2'ye diyeceğiz ki “Bu sınıflar sana emanet, bunları isteyen olur ise vereceksin” . ( Bu arada kurucu yöntem injectionu kullanacağız )
Amacımız şu 1 sınıfı ( War sınıfı aşağıda paylaşıyor olacağız ), üstteki 2 sınıfa bağımlı etmek.
@Component Annotationunu Ekleyelim
Daha önce dediğimiz gibi Component annotationu neylerin nasıl injection olacağını Dagger 2 ye söyler. Şimdi “BattleComponent” adında bir interface oluşturduk.
Bu interface bize bağımlılıkları ile “War” nesnesini oluşturacak ve bir sadece “getWar()” metodu ile istediğimiz “War” objesine ulaşabileceğiz.
Şimdi projeyi tekrar rebuild etmemiz gerekiyor
Rebuildten sonra “DaggerBattleComponent” sınıfımız oluşturulduğu için çağırabileceğiz. Şimdi “War” sınıfını çağırabiliriz.
Gördüğünüz gibi “Starks” ve “Boltons” sınıflarını oluşturmadan “War” sınıfını oluşturduk ve istediğimiz gibi kullanabiliyoruz.
Gelin Dagger 2 ile Basit bir Android Projesi Yapalım
Şimdi olayımız şöyle olacak. Bir çiftliğimiz var ve bu çiftlikte hayvanlarımız( koyun ve inek ) var ve bu hayvanları otlatacağız bakalım bunu Dagger 2 ile nasıl yapacağız.
Gradle (app) aşağıdakileri yazıyoruz
Şimdi hayvanlarımızı oluşturalım.
İnek sınıfını oluşturmak ile başlayalım.
Inek sınıfımızı oluşturduk ve inek sınıfına “otla()” adlı bir yöntem ekledik. Bu yöntem çağırılınca Log ekranında “Inek otluyor” diye mesaj yazdıracak.
Koyun ile devam edelim :)
Koyun sınıfımızı oluşturduk ve bu sınıfa da “otla()” adlı yöntemi ekledik.
Aslında olması gereken şu “Hayvan” adında bir interface oluşturup bu interfaceyi “Koyun” ve “Hayvan” sınıflarında implement etmek ama daha iyi anlaşılsın diye böyle bir yola başvurdum.
Şimdi Çiftlik sınıfımızı oluşturalım. Bu sınıfımız “Inek” ve “Koyun” objelerini kurucu yönteminde parametre olarak alıyor olacak. Ve “yemekYedir()” diye bir metodu olacak. Bu metod “Inek” ve “Koyun” ları otlattıracak.
Şimdi kullanacağımız sınıfları oluşturduğumuza göre bu sınıflar arasındaki ilişkiyi Dagger 2'ye tanımlamaya gelelim. Bu tanımlama sürecinde “@Module” , “@Singleton” ve “@Provide” adındaki annotationların ne işe yaradığını ve bu annotationları nasıl kullanacağımıza değineceğim. Bu annotationlara daha önceki (aşağıda) bir yazımda değinmiştim ama burada daha detaylı anlatacağım.
@Module Annotationun Eklenmesi
Modül sınıfımızı oluşturmamız lazım ama ondan önce @Module annotationu ne işe yarar ondan bahsedelim. @Module sınıfları/modülleri işaretler. ( Nasıl açıklama ama )
@Provides Annotationun Eklenmesi
Modül sınıfımızda @Provides adlı bir annotation görüyorsunuz. Peki ne bu “@Provides” ? Aslında bunun için “Provide” kelimesine bakmamız yeterli. Provide İngilizce’de “sağlamak” anlamına geliyor. Yani @Provides annotationunu eklediğiniz bir objeye ihtiyaç duyan bir yer olunca Dagger 2 geliyor ve bu objeyi buradan alıyor.
Modül sınıfını oluşturduğumuza göre Component sınıfımızı oluşturabiliriz.
@Singleton Annotationun Eklenmesi
Singleton annotationunu eklediğiniz bir obje veya sınıf sadece bir kez oluşur. Bu sayede uygulamayı 1 obje üzerinden yönetebilirsiniz.
Gördüğünüz gibi inject edeceğim sınıfı belirliyorum. Yani diyorum ki; “Dagger 2 ben MainActivity üzerinden seni çağıracağım”
Şimdi MvpApp dosyamızı oluşturacağız. Tamamiylen ezbere oluşturulan bir dosya. Bağımlılıkları kullanacağımız sınıfta kullanmak için oluşturulan bir sınıf. ( Şuan Github Gist’te bir sorun olduğu için kodların Screen Shoot’larını paylaşıyor olacağım )
Şimdi MvpApp sınıfımızı Manifest.xml dosyasında tanımlayalım. Bunun için Manifest dosyasına gelip Application tagleri arasına gelip name adlı bir değişkene .MvpApp demeniz yeterli.
Şimdi Ciftlik sınıfını kullanacağımız MainActivity’e gelelim ve Ciftlik sınıfını inject edelim.
Sonra MvpApp sınıfımızı tanımlayıp. Ciftlik sınıfının “yemekYedir()” fonksiyonunu çağıralım.
Bir flashback yapalım Ciftlik sınıfından yemekYedir() fonksiyonunu çağırdığımız zaman ne yapıyordu?
Inek ve Koyun sınıfının “otla()” fonksiyonunu çağırıyordu. Bu fonksiyon Log ekranına mesaj yazdırıyordu. Şimdi projeyi run edelim sonuç ne birlikte görelim.
Evet logluyor ama nasıl?
Ciftlik sınıfını tanımlamadık sadece global bir değişken olarak Inject ettik ve üstüne üstlük Ciftlik sınıfına “Inek” ve “Koyun” sınıflarını parametre olarak MainActivity sınıfı içinde vermedik. Şöyle bakalım olaya;
Anneniz size dün akşam makarna yapmış ve dün yediğiniz makarna artmış. Ertesi gün gelince eve annenizden makarna istediğinizi söylüyorsunuz. Anneniz size tekrar makarna yapmak yerine dün yaptığı makarnayı size verecektir. En azından benim annem böyle yapıyor :)
En azından Dagger 2 de böyle çalışıyor. Dagger 2 bir sınıf istendiği zaman “Modül” sınıfında oluşturulmuş olan objeyi önünüze koyar. Sizde onu afiyetle kullanırsınız.
Sizlere Dagger 2 ile ilgili anlatacaklarım bu kadar. Oluşturduğumuz projenin kaynak kodları aşağıdaki linkte.