Android Günlüklerim | ViewBinding
Bir nesil findViewById ile kullanacağı her bir XML elemanına ayrı değişken oluşturup resource yolundan id bilgilerini çeke çeke tasarım elemanlarına erişmiştir. Native android programlamaya tekrar yoğunlaştığım bu günlerde ben de bu nimetin faydasını yeni tatmışken , öğrendiğim naçizane bilgilerimi sizlerle paylaşacağım. Bakalım neymiş bu ViewBinding.
Tanım
ViewBinding , görünüm elemanlarını, oluşturduğu binding sınıfı nesneleri ile erişip yönetebilmeyi sağlayan bir android jetpack modülü.
Nasıl Çalışıyor?
ViewBiding , görünüm elemanlarının id bilgilerini içeren bir Java sınıfını bizim yerimize oluşturuyor. Modüldeki her bir görünüm için bir adet sınıf oluşuyor ve biz Android Studio’da düzenlememizi yaptıktan sonra yalnızca düzenleme yaptığımız görünümle ilişkili olan binding nesnesi güncelleniyor. Bu da derleme süresini optimize ediyor.
Buraya kadar tamam , şimdi yeni açtığımız bir projede ViewBinding’i nasıl aktif ediyoruz onu görelim,
ViewBinding Kullanmaya Başlamak
Modül düzeyindeki build.gradle dosyamızda android etiketleri arasında herhangi bir yerde ,
android {
...
buildFeatures {
viewBinding = true
}
}
şu şekilde yapıştırmanız yeterli. Artık ViewBinding özelliğinden faydalanabiliriz.
Şimdi birkaç ufak örnekle ViewBinding kullanımını görelim. Öncelikle bir aktivite üzerinde ViewBinding nesnesini oluşturup görünümümüze bağlayacağız. Ardından görünüm içindeki bir TextView alanına erişeceğiz.
Activity Üzerinde ViewBinding
activity_main.xml dosyamızda erişmek istediğimiz alan şu şekilde olsun.
<TextView
android:id="@+id/activityTextView"
android:layout_margin="16dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:textColor="@color/black"
android:textSize="20sp" />
Ardından MainAcitivty.kt içerisinde bizim için oluşturulmuş olan ActivityMainBinding türündeki nesnemizi tanımlayalım.
private lateinit var activityMainBinding : ActivityMainBinding
Daha sonra ViewBinding objemizi görünümümüz ile bağlıyoruz. Bunun için onCreate() methodu içinde setContentView’e parametre olarak binding objesinin getRoot() property’sini geçiyoruz (Kotlin yazıyorsanız direkt root). Bu root property’si ilişkili olan görünüme ait kök layout’u size verecektir. Örneğimizde MainActivity.xml içinde kök layout olarak RelativeLayout kullandık ki getRoot() dönüş tipinin de bu şekilde olduğunu görebilirsiniz.
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState) activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
}
Şimdi activityMainBinding objesi üzerinden görünümümüze erişip id değeri activityTextView olan elemanımızın değerini değiştirebiliriz.
private fun changeText(){
activityMainBinding.activityTextView.text = "Changed by ViewBinding"
}
İşte bu kadar :).
Şimdi işi biraz daha ileriye götürelim ve fragmentlarla ViewBinding işlemlerine bakalım. Hatta bunun için bir RecyclerView kullanalım. Bakalım adaptörümüzde ne gibi değişiklikler olacak.
RecyclerView Adaptör Sınıfında ViewBinding Kullanmak
Öncelikle RecyclerView içinde göstereceğimiz veriler için ufak bir model oluşturalım. Tek satırlık modelimiz şöyle olsun:
data class RecyclerItemModel(val imageMipmapSource: Int?,val text:String?)
Ardından RecyclerView içerisinde her bir elemanımızın görünümünü temsil edecek olan bir layout daha oluşturalım. Buna da recycler_item ismini verelim. Ardından bir ListFragment.kt sınıfı açalım ve fragment_list.xml içinde RecyclerView elemanınızı ekledikten sonra bir FragmentContainer olarak görünümümüzü activity_main.xml içerisine yerleştirelim. Layout içeriklerine yazı sonundaki github linkinden ulaşabilirsiniz.
Ardından RecyclerAdapter.kt sınıfımızı yazmaya başlayalım. Adapter sınıfımız şu şekilde,
Adapter sınıfımıza elemanlarımızı ListFragment üzerinden bir liste olarak vereceğimiz için recyclerItems parametresini sınıfımıza geçiyoruz. Burada ViewHolder sınıfında dikkat ederseniz bir itemView yerine binding nesnesi geçtik. Bu binding nesnesi tipi her bir RecyclerView elemanlarımızın temsili için oluşturduğumuz recycler_item.xml görünümünün binding sınıfı olan RecyclerItemBinding olacaktır. Oluşturulan bu binding sınıflarının isimlendirilmeleri örneğin activity_main.xml için ActivityMainBinding şeklinde olurken fragmentler için de örneğin fragment_list.xml için FragmentListBinding şeklinde olmaktadır. Ardından RecyclerView.ViewHolder sınıfına binding’in root property’sini geçerek bağlama işlemini tamamlıyoruz.
Bir başka dikkat edilecek husus da onCreateViewHolder içerisinde binding nesnemizi bağlarken activitylerden farklı olarak ViewGroup nesnesini de inflate methodunda geçmemiz gerektiğidir. Eğer geçmezsek emülatörünüzde istenmeyen sonuçlar olabilir ve benim gibi stackoverflow’da konu açmak durumunda kalabilirsiniz :).
Binding nesnemizi de bağladıktan sonra artık onBindViewHolder içinde RecyclerViewHolder üzerinden recycler_item.xml içindeki alanlara erişebiliriz ve gelen değerlerini atayabiliriz. Adaptör içerisinde ViewBinding kullanımı da bu şekildeydi. Bir de fragment içine bakalım..
Fragment’da ViewBinding
Activity’de olduğu gibi binding nesnemizi oluşturalım, bu sefer nullable yapacağız. Sebebini açıklayacağım.
private var _fragmentListBinding: FragmentListBinding? = null
private val fragmentListBinding get() = _fragmentListBinding!!
Ardından onCreateView içinde binding nesnemizi bağlıyoruz. Adapter sınıfında olduğu gibi ViewGroup parametresini de inflate ederken veriyoruz.
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
_fragmentListBinding = FragmentListBinding.inflate(layoutInflater,container,false)
return fragmentListBinding.root
}
Ardından istediğimiz işlemleri yapabiliriz. RecyclerView için adaptörümüzü fragmentListBinding aracılığı ile erişip bağlayabiliriz.
fragmentListBinding.recyclerView.layoutManager = LinearLayoutManager(context)
fragmentListBinding.recyclerView.adapter = recyclerAdapter
recyclerAdapter.recyclerItems = itemList
recyclerAdapter.notifyDataSetChanged()
En son ise binding objemizi görünüm sonlandığında null edelim ki memory leak falan olmasın. Malum fragmentlar activitylerden daha uzun yaşıyor :).
override fun onDestroyView() {
super.onDestroyView()
_fragmentListBinding = null
}
Ekranımız da şöyle gözükecektir. Sıkıntısız çalışıyor gibi :).
Bu yazıda ViewBinding konusunu sade bir şekilde anlayıp aktarmaya çalıştım. Umarım faydalı olmuştur. Kodların tamamına aşağıdan ulaşabilirsiniz. Geri dönüşleriniz için de lütfen çekinmeyin. Sonraki konumuz ise DataBinding olacak gibi 🎈. Sağlıcakla 🎉.
Github
Referanslar