Android'de Data Binding

Herkese selamlar. Bugün oldukça geniş bir konu olan Data Binding‘i elimden geldiğince ifade etmeye çalışacağım. Biraz uzun bir yazı olacak. Kahveler hazırsa hadi başlayalım.



Görsel Referansı


Kotlin 1.40.20-M2 güncellemesi ile Kotlin Android Extensions içerisinde kullanılan Synthetic'in devre dışı bırakıldığını duymuşuzdur. Peki bu ne anlam ifade ediyor? Artık oluşturduğumuz component;lere direkt ulaşamayacağız. Çözüm olarak ViewBinding, Data Binding veya findViewById kullanmamız gerekecek.


Data Binding Nedir?


Data Binding bir Android Jetpack öğesidir. XML içerisinde değişken tanımlayıp bu değişkenleri component'ler üzerinde farklı amaçlarla kullanmamıza olanak tanır. XML ile Model'in iletişimine imkan verir de diyebiliriz.


Data Binding Neye Çözüm Sunuyor?


Bir konunun iyi bir şekilde anlaşılması için neye çözüm sunduğunu anlamak oldukça önemlidir. Component‘ler üzerinde değer ataması, visibility, onClick, onTextChange gibi ifadelendirmeleri XML üzerinden yönlendirebilmemize olanak tanıyor. Böylelikle ekstra kod kalabalığından kurtuluyoruz. Ayrıca componentler için BindingAdapter da oluşturabilir, bu adapter‘larla dilediğimiz birçok işlemi gerçekleştirebiliriz. Data Binding ile Observable kullanılarak değerler değiştiğinde otomatik olarak component'ler üzerinde değişiklik yapabiliriz. Bu ve bunun gibi birçok alanda çeşitli çözümler sunmaktadır.


Yukarıda bahsettiğim gibi aslında çok uzun bir konu. Data Binding için seri şeklinde yazılmış bloglar mevcut. Elimden geldiğince ifade etmeye çalışacağım. Öyleyse haydi inişe geçelim.

İlk olarak basit bir şekilde nasıl Data Binding kullanılır onunla başlayalım.



Build.Gradle(APP)


plugins {..
id 'kotlin-kapt'}
buildFeatures {
    dataBinding true}

Basit bir market modeli oluşturup xml üzerinden bu verileri görüntüleyeceğiz.



Market Data Model



Activity Tasarımı


Alt+Enter kısayolu ile XML tasarımınızı data binding formatına dönüştürebilirsiniz. Data Binding kullanmak için tüm XML'in <layout> tag’leri içerisinde yer alması gerekmektedir.


<data> içerisinde çeşitli <variable/>’lar tanımlayıp dilediğiniz type'ta değişken tanımlamaları yapabilirsiniz. Biz market model type’ında bir değişken tanımlaması yaptık. Bu değişkenin değerlerini TextView'lerde görüntülemek için ise, Text kısımlarına “@{degiskenAdi}” tanımlamalarında bulunduk.


Bu noktada binding expressions ile ne tür tanımlamalar yapabileceğinize dair bir kaynak paylaşıyorum, buradan göz atabilirsiniz.



Activity


Oluşturduğumuz Data Binding veri kaynağının belirtilmesi ve hangi sayfanın tasarımı olduğunu tanımlamak için Activity içerisinde ActivityMainBinding'den instance oluşturuyor ve gerekli tanımlamaları ifade ediyoruz (Tabii ki bu sizlerin class adlarına göre değişiklik göstermektedir). Ardından XML içerisinde tanımladığımız market modelinin değer atamasını gerçekleştiriyoruz. Peki şimdi sonucu görüntüleyelim.


Şu anlık TextView‘ler üzerinde Data Binding ile nasıl text ataması yapılır, onu ifade ettik.


"Peki bu işlem bizleri nelerden kurtardı? Normalde de bu işlemleri gerçekleştiriyorduk." dediğinizi duyar gibiyim.


Yazımın başlarında da belirttiğim gibi Kotlin tarafından Synthetic devre dışı bırakıldı. Bu yüzden findViewById kullanmamız gerekebilirdi. Ayrıca tüm TextView’lerin text atamalarını da tek tek tanımlamanız gerekirdi. Sizce de basit bir işlem için bile oldukça uzun kod satırları değil mi? Bir de yapacağınız işler daha kompleksleşince bir düşünün. Tercih sizin. Öyleyse haydi biraz daha devam edelim.



BindingAdapter


BindingAdapter'ları XML içerisindeki fonksiyon tanımlamaları gibi düşünebilirsiniz. Var olan parametrelerin dışında kendimize özgü işlevlerin yapılmasını istersek o zaman bindingAdapter’a ihtiyacımız olabilir. Şu anki uygulamamız için Glide kullanarak bir resim görüntüleyelim. Manifest içerisine internet izni vermeyi unutmayınız.


<uses-permission android:name="android.permission.INTERNET" />
def swipeRefreshLayout = '1.1.0' 
def glideVersion = '4.9.0'
implementation "com.github.bumptech.glide:glide:$glideVersion"
implementation "androidx.swiperefreshlayout:swiperefreshlayout:$swipeRefreshLayout"

“@BindingAdapter()” içerisinde dilediğiniz isimlendirmeyi kullanabilirsiniz. Dışarıdan almak istediğiniz parametreleri de normal fonksiyon tanımlamalarında olduğu gibi ifade edebilirsiniz. Fonksiyon içerisinde ise Glide işlemlerini tanımlıyoruz. Ayrıca bu fonksiyonu ImageView’a Extension olarak yazdığımız için this ile ImageView’a erişebilirsiniz. Tabii ki BindingAdapter‘ları Extension olarak yazmak bir tercihtir, böyle bir zorunluluk mevcut değil.


Glide, bizim için tanımladığımız URL'den Image‘ı alıp ImageView'da görüntülenmesi için gerekli işlemleri yapıyor. Xml içerisinde “loadImage” ı tanımlayıp alması gereken parametreyi market modelinden karşılıyoruz. Şimdi projemizi çalıştıralım.



Böylelikle URL bağlantısı olan bir resmi ImageView de görüntülemek için Glide kütüphanesini BindingAdapter ile nasıl kurgulayacağımızı görmüş olduk. Bunun gibi farklı amaçlara hizmet eden özel BindingAdapter‘lar tanımlayabilirsiniz.

Şimdi, MVVM içerisinde RecyclerView — ViewModel — ViewState gibi yapılarda Data Binding nasıl yer alıyor onları inceleyelim.


Şu an yapacağımız 2. projeyi yazının sonundaki GitHub reposundan, MVVM-DataBinding branch‘inden ulaşabilirsiniz.


Market modeli üzerinden devam edeceğiz. Markette yer alan ürünleri listeleyip, detay sayfalarını tasarlayacağız. Home ve Detay sayfası içerisinde LiveData, ViewState gibi konuları işleyeceğiz. Bu işlemleri yaparken belli adımları es geçeceğim. Önceki yazılarımı inceleyebilir veya farklı kaynaklardan o alanda eksikleriniz varsa giderebilirsiniz.


Uygulamamızın HomeFragment’ı için senaryomuz şu şekilde olacak: Ana sayfada marketteki ürünleri listelerken, eğer stok adeti 10 un altında ise, Fiyat bilgisi için 2 farklı değişikliğimiz olacak. Fiyat bilgisi kırmızı renkte ve “%50 indirimli” şeklinde görüntülenecek. Ayrıca item‘ın background‘unun yeşil renkte olmasını istiyoruz.


Peki bu işlemi RecyclerView içerisinde Data Binding kullanarak nasıl kurgulayabiliriz ViewState bu noktada tercih edilebilir.


HomeFragment


Binding ve Adapter tanımlamalarımızı belirtiyoruz . Ayrıca binding’e lifecyclerOwner tanımlarsanız binding’in yaşam döngüsü Fragment’ın yaşam döngüsüne sahip olur.



Market Adapter


Her gelen market modelini MarketViewHolder içerisindeki bind fonksiyonu ile ViewState‘e yönlendiriyoruz. XML'de ise artık market modeli değil ViewState değişkenini oluşturuyoruz. Değer atamaları, renk değişiklikleri, visibility gibi birçok işlemi viewState üzerinden gerçekleştirebiliriz.


ViewState


Senaryoda bahsettiğimiz UI Business Logic‘i kontrol edebilmek için ViewState kullanıyoruz. ViewState, bizlerin market modelini kullanarak veriler üzerinde işlemler yapıp XML içerisindeki component'lere farklı değerlerin gönderilmesi için imkan tanıyor. Senaryomuz dışında UI ile ilgili farklı reaksiyonlar alınacaksa sadece ViewState içerisinde değişiklik yapmamız yeterli olacaktır. Şimdi ise son adım olan XML içerisine bir göz atalım.


Market Item Tasarım


Senaryoda istediğimiz renk değişimini elde etmek için companent'lerde isDiscountColor fonksiyonunu kullanıyoruz. Bu fonksiyon bizlere belirtilen şartlar sağlandığında farklı renk kodlarıyla geri dönüş sağlıyor. tvPrice için ise senaryoda belirtilen şarta göre dönen text değerleri farklılık gösterebiliyor. Diğer component‘lerin text atamaları az önce ifade ettiğimiz örnekteki gibi kullanılıyor.



Evet sevgili dostlar, yazı biraz uzuyor farkındayım ama gelin son bir konuya daha değinip ardından vedalaşalım.


Şimdi ise şöyle bir senaryo düşünelim: Ürünlere tıklandığında detay sayfamız açılsın ve bu sayfa içerisinde 1 saniyede ürün 5 adet azalsın ve ürün adeti 0 olunca tükendi yazısını görüntüleyelim. Ardından kullanıcı ürün adına basınca ürün adetini yeniden yükleyelim. Ayrıca tüm bu işlemleri ViewModel üzerinden gerçekleştirelim.


ViewModel


Neler yazdık biraz açalım. Market modelimizi XML tarafında işlemek için market adında bir değişken tanımladık.


count ve soldOut değişkenleri LiveData olarak tanımlandı. Bunun nedeni ise bu değişkenlerin değerleri değiştiği zaman XML tarafında otomatik bir şekilde bu değişimin tetiklenmesini istememiz.


minusCount metotu içerisinde her saniyede ürün adetinin 5 azalmasını ve ürün adeti 0 olduğunda tükendi yazısının görüntülenmesini sağlayacak şekilde logic tasarladık.


onClick, ürün adına basıldığında, ürün sayısının yeniden tanımlanması için çağırımlarda bulunduk.


Peki XML tarafında bunu nasıl kurguluyoruz, Hadi şimdi de oraya bir bakalım.


Detay Tasarım


Text‘lerin görüntülenmesi için şimdiye kadar yaptığımız şekilde market model’ine ulaşıp dilediğimiz değerleri görüntülüyoruz. Ekstra olarak count ve price bilgileri için Int-toString dönüşümü gerçekleştirdik.


Tükendi için ivSoldOut ImageView‘ın visibility özelliğine ViewModel içerisindeki soldOut LiveData değerini tanımladık. Böylelikle bu değer her değiştiğinde bu component‘in visibility özelliği de tetiklenecek. Ekstra olarak default gone tanımlamasında bulunduk. Visibility, değer ataması yapabilmek için <data> içerisine view ‘ı import etmeniz gerekmektedir.


tvName, onClick özelliğine ViewModel'da oluşturduğumuz onClick metodunu tanımlıyoruz. Bu metodun view parametresi alması gerektiğini de unutmayalım.


Detay Fragment


Detay Fragment içerisinde Data Binding ve ViewModel tanımlamalarını gerçekleştiriyoruz.




Evet dostlar, uzun bir yazı oldu fakat konu içerisinde birçok farklı kullanım olduğu için o alanlara da elimden geldiğince değinmek istedim. Değinmediğim farklı kullanımlar da tabii ki mevcut. Yazmak için değil, bilgi aktarımında bulunmak için çabaladım. Umarım faydalı bilgilerde bulunabilmişimdir. Keyifli kodlamalar.


Dilerseniz DataBinding  -  Android CodeLab'e buradan ulaşabilirsiniz.


GitHub: https://github.com/rcpyesilkaya/DataBinding-Sample


Kaynak: https://developer.android.com/topic/libraries/data-binding/


#android #kotlin #databinding

0 yorum

Son Paylaşımlar

Hepsini Gör

Komünite

Platform

Mobiler.dev Anasayfa
  • Twitter
  • Instagram
  • development_düzenlendi_düzenlendi
  • Youtube
  • slack-icon-black_edited_edited_edited
  • Gri LinkedIn Simge
imageedit_2_9667998092.png
JetBrains Hakkında Detaylı Bilgi Alın

© 2021 by mobiler.dev

Kurumsal Yazar Hesapları

adesso.png
mobilerdevLogo.jpg
Yazarlık Başvurusu Hakkında Bilgi Alın, Başvuru Yapın.
Topluluk Yazarlarını Tanıyın