Kotlin İle Retrofit Kullanımı
Herkese selamlar sevgili dostlar, Bugün sizlere uzak sunucudan verilerimizi Retrofit & RxJava ile nasıl elde edebileceğinizi anlatmaya çalışacağım. Hadi birlikte başlayalım
Retrofit
İnternet deki veriler ile çalışmak istediğimiz de kullanmanız gereken bir kütüphanedir. Api üzerindeki datalar ile GET,POST,UPDATE,DELETE gibi işlemleri yapmamıza olanak sağlar. Retrofit yerine geçmişte AsycnTask’ler ve Volley gibi yapılar kullanılmaktaydı. Fakat endüstride en çok tercih edilen yapı Retrofit’tir.
Retrofit Method Type
Uzak sunucular ile iletişime geçerken çeşitli metotları kullanırız. Bu metotlar ile listeleme, güncelleme gibi işlemler yapılır.
POST : Uzak sunucuda dosya oluşturma işlemidir. Her post işleminde bu dosya tekrardan oluşturulur.
PUT : POST ile benzerdir, ancak mevcut bir varlığın yerine kullanılır. Yani override işlemi gerçekleştirir. Verileri güncelleme işleminde daha sık kullanılır. Güncelleme işleminde tüm bilgiler yeniden gönderilmelidir.
PATCH : PUT’a benzer yapıya sahiptir. Ancak sadece update edilmesi istenilen alan gönderilir.
GET : Uzak sunucudan verileri listeler.
HEAD : Yalnızca yanıt başlıklarını döndürür.
DELETE : Uzak sunucudaki verileri siler.
Get ile atılan istekler’de url takibi yapılabilir. PUT ile bu url gizlenerek istek atılabilir.
Url içerisindeki veriler de eğer değişken varsa bizler bu değişkenleri path ve quarey ile gönderebiliriz. Örnek olarak “..com/235/…?api_key=xxx” deki “235” değerini “@Path” ile Api Key gibi ifadeleri ise “@Quarey” ile belirtebiliriz.
Converter
Retrofit kullanırken aynı zamanda bir converter da kullanmamız gerek. Genel olarak kullanılan converter’lar “Gson, Jackson, Mushi “diye sıralayabiliriz. Aynı zamanda bunların dışında da bir çok converter mevcuttur. En çok tercih edilen converter Gson’dır. Jakson ise büyük datalar ile işlem yaparken tercih edilebilir.
RxJava
Senkron : Bir iş bitmeden diğer iş yapılmaz. Kullanıcı internetten alınacak datanın sonucu gelmeden herhangi bir işlem yapamaz.
Asenkron : Birden fazla iş oluşturulup işlemler yapılır. Kullanıcı internetten veri alırken aynı zamanda uygulamayı kullanmaya da devam edebilir.
RxJava ile yapacağımız işlemleri Asenkron bir şekilde gerçekleştiririz. MainThread’i bloklamayıp, yani kullanıcının ekran üzerinde işlem yapmasını engellemeden. Farklı Thread’ler üzerinden işlem yapmamıza olanak sağlar. Bu yapı sayesinde UI da kilitlenmeler oluşmaz. Eğer çok kompleks yapılar kullanmıyorsak sadece Retrofit ile de datalarımıza ulaşabiliriz.
RxJava için daha detaylı bilgiye ulaşmak isterseniz aşağıdaki bloğu inceleyebilirsiniz.
Konuyu daha detaylı anlamak için birlikte bir proje üzerinden devam edelim.
Projeyi yaparken https://ezanvakti.herokuapp.com/ api’yi kullanacağız
İnternet işlemlerinizi farklı bir modül açarak da yapabilirsiniz. Bu açacağımız modülün kendisine özgü build.Gradle ve manifest’i vardır.
Projeyi ilk açtığımızda network işlemleri için farklı bir modül oluşturalım. Bu modül içerisinde RetrofitClient’ımızı tanımlayacağız.
Build.Gradle(App)
Gradle içerisine oluşturduğumuz modülü implement ediyoruz.
implementation project(":retrofitnetwork")
Build.Gradle(retrofitnetwork)
Kullanacağımız kütüphaneleri gradle içerisinde tanımlamasını gerçekleştiriyoruz.
def retrofitVersion = '2.4.0'
def rxJavaVersion = '2.1.1'
def lifecycleVersion = "2.2.0"
def okHttpVersion= "2.2.0"//lifecycle
api "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycleVersion"//retrofit
api "com.squareup.retrofit2:retrofit:$retrofitVersion"
api "com.squareup.retrofit2:converter-gson:$retrofitVersion"
api "com.squareup.retrofit2:adapter-rxjava2:$retrofitVersion"
//rxjava
api "io.reactivex.rxjava2:rxjava:$rxJavaVersion"
api "io.reactivex.rxjava2:rxandroid:$rxJavaVersion"//okHttp3
implementation "com.squareup.okhttp3:logging-interceptor:$okHttpVersion"
Impelementation - API Farkı
Bir modül içerisinde dependencies eklerken implementation ile api arasında farklılıklar vardır. Api ile o modül içerisinde ki kütüphane eklentilerini implement ettiğiniz modüllerde kullanabilirsiniz. Fakat implementation ile eklediğiniz kütüphaneleri sadece o modül içerisinden kullanabilirsiniz.
Örneğin biz Retrofit ve RxJava’yı implementation ile ekleseydik. App modülü içerisinde retrofit ve rxjava kütüphanelerini kullanamazdık. Gradle.App içerisine tekrardan tanımlama yapmamız gerekirdi.
BuildTypes — ProductFlavors
BuildTypes : Program içerisinde build işlemi yapılırken kullanılacak işlemler BuildTypes içerisinde tanımlanabilir. Build sürecini hızlandırmak veya log’ları değiştirmek için kullanılabilir. Debug ve Release diye 2 farklı case genelde kullanılır daha farklı kullanımlar da mevcuttur. Debug da çeşitli sınırlamalar içertebiliriz. Relase de ise daha kapsamlı ve ayrıcalıkların giderildiği bir build işlemi yapılır. Uygulamanın APK’sı alınırken Debug veya Relase olarak tanımlanabilir.
ProductFlavors : Ürün ile ilgili işlemler yaparken ProductFlavors içerisinde tanımlama yaparız.
flavorDimension “api”,”production” gibi tanımlamalar yapılır. Bu ifadeler Dikey diye adlandırılabilir. Api ile uygulama içerisinde uzak sunucudan veriler alınırken BASE_URL değişiklik gösteriyorsa Api dikeyi ile gerekli ayrıştırmalar yapılabilir.
Production tanımlaması ile uygulamanın freemium-premium gibi özellikleri sağlanabilir.
Bu dikeyleri kullanmak için productFlavors içerisinde tanımlamalar yaparız. Burada dilediğiniz gibi isimlendirme yapabilirsiniz. Örneğin api dikeyi için “dev-prep-prod” diye 3 farklı BASE_URL tanımlamak istiyoruz. Dev{ } dedikten sonra dimension ile hangi dikeyi kullanacaksam belirtiyorum. Daha sonra gerekli BASE_URL tanımlamasında bulunabilirim. ProductFlavors içerisindeki tüm tanımlamalar bir dimension içermelidir. Eğer farklı bir dikey için tanımlama yapacaksam yine productFlavors içerisinde dilediğiniz tanımlamayı yapabilirsiniz. Örneğin “freemium-premium” bunların tanımlamalarını yaparken, Fremium{} yazıp içerisine yine hangi dikeyi kullanmak istiyorsak dimension olarak belirtebiliriz.
Build.Gradle(retrofitnetwork)
Uygulamamız için namaz vakitlerinin olduğu bir api’yi kullanacağız. İlgli BASE_URL tanımlamasını bu alan içerisinde tanımlıyoruz. Farklı URL adreslerine sahip olsaydık. Onların ayrımını da buradan tanımlayabilirdik. Uygulama APK’sı da burada tercihimize göre değişiklik gösterebilmektedir.
android {...
flavorDimensions "api"
productFlavors {
dev {
dimension "api"
buildConfigField 'String', 'BASE_URL', '"https://ezanvakti.herokuapp.com/"'
}
}
}
Manifest-app
Unutmadan manifest içerisinde internet iznimizi belirtelim.
<uses-permission android:name="android.permission.INTERNET"/>
Evet artık her şey hazır. Şimdi işleri biraz daha kızıştıralım. Şöyle ki ilk önce bir model oluşturacağız. Daha sonra bir interface tanımlayıp GET işlemlerimizi yazacağız. RetrofitClient ile de retrofit tanımlamasını yapıp verilerimizi listeleyeceğiz. RetrofitClient işlemlerini praynetwork modülünde geri kalan tüm işlemleri app modülünde gerçekleştiricez.
PrayModel
Api deki verilerin birebir isimleri ile modelimizi oluşturuyoruz. Dilersek SerializedName kullanıp değişken isimlerinde değişiklik yapabilirdik.
Aynı zamanda AndroidStudio’da var olan bir eklenti ile de modellerinizi oluşturabilirsiniz.
Chrome eklentilerinden JSON Viewer’ı kurarak JSON verileri formatlı bir şekilde tarayıcınızda görüntüleyebilirsiniz.
PrayApiService
Api’ye GET isteği atıyoruz. Kullanıcıdan alacağımız id değerine göre veriler değişiklik göstermektedir. Bu yüzden id değerini “@Path” ile kullanıcıdan alıp url de tanımlıyoruz. Bu noktada api_key mevcut ise “@Query” ile bu değeride tanımlayabilirsiniz.
Yapacağınız işlemlere göre “GET-PUT-PATCH-DELETE” gibi metotlar dan hangisini kullanacağınızı genelde api dokümanında belirtilir.
RetrofitClient
RetrofitNetwork modül içerisinde RetrofitClient adında bir abstract class tanımlıyoruz. Bu class içerisinde Singleton yapısında Retrofit’i inşa ediyoruz. Eğer daha önce bir instance oluşturulmuş ise bir daha oluşturmadan var olan instance’ı return ediyoruz. İlk defa çağırılıyorsa Retrofit build ediliyor.
Converter olarak Gson kullanıyoruz, Base_url’i product flavors da tanımladığımız ifade den alıyoruz. BuildConfig import işlemi gerçekleşmiyorsa projeyi clean ve rebuild yapınız. okHttpClient sayesinde Log lar takip edebiliyoruz.
PrayRepository
Burada verilerin network ten mi? Yoksa local den mi ? okunacağının kontrolü gibi farklı lojiker kurabiliriz. Elbette repository de yaptığımız işlemlerin aynısını ViewModel içerisinde de yapabilirdik. Fakat burada belli bir süre geçmemişse local den al geçmişse network ten al gibi lojik leri viewModel da tanımlamak olmayacaktır. Bu yüzden belli lojik mantıklarını Repository içerisinde halledip viewModel’a al kardeşim istediğin veriler bunlar demeliyiz.
subscribeOn : Yeni bir zamanlayıcı oluşturuyoruz.
observeOn : MainThread’de gözlemleyici tanımlıyoruz.
subscribeWith : Verimizi alırken single call’ını kullanıdığımız için DisposableSingleObserver kullanmamız gerekli. Aksi takdirde bu metod çalışmayacaktır. İlgili Observeble’ı kullanmak sorunu çözecektir. Single’ın bize sağladığı bir avantaj ise onSuccess ve onError metotlarıdır. Veriler yüklenirken başarılımı yoksa hatalı mı olduğunun kontrolünü sağlıyor. Observeble olarak verilerimizi çekseydik bu yapı metotları kullanamayacaktık.
Disposable : Kullan at olarak tanımlayabiliriz. Disposable sayesinde threadler de kullanılmayacak işlemleri tutmamış olur performans kaybının önüne geçeriz.
PrayViewModel
UI veri aktarımında bulunacak class dır. ViewModel içerisinden Repository’e ulaşılır ve datalar çekilip UI’ya gönderilir. Buradaki değişimleri yakalamak için MutableLiveData ve LiveData kullanırız. MutableLivedata’yı private tanımlamak daha doğru olacaktır. Çünkü bizler değiştirilebilir dataların UI tarafından değiştirilmesini istemeyiz. Bu yüzden 2. Olarak tanımladığımız LiveData’nın get metoduna MutableLivedata’yı atıyoruz. Böylelikle sadece ViewModel içerisinden datanın değeri değiştirilebileceğini garantiliyoruz. onCleared metodu ile kullan atlarımızı temizliyoruz.
UI - MainActivity
ViewModel’ımızı UI içerisinde tanımlıyor ve butona basılınca viewmodeldaki ilgili metot çalıştırılıyor. LiveData olarak tanımladığımız değeri gözlemliyoruz ve çekilen datalar Logcat de yazdırılıyor. Datalar elinizde geri sizde sevgili dostlar.:)
Retrofit & RxJava bloğumun sonuna geldik umarım faydalı bir şeyler aktarabilmişimdir. Geri dönüşleriniz benim için değerlidir. Sağlıklı Günler, Keyifli Kodlamalar Dilerim. Bir sonraki yazımda görüşmek dileğiyle.