Data Binding — temeller, Android'de çift yönlü bağlama

Yazar: IT Sectr Yayınlanma: 2026-02-20 Okuma süresi: 8 dk

Data Binding — bildirimsel sözdizimi aracılığıyla XML düzenlerindeki UI bileşenlerini uygulama kodundaki veri kaynaklarına bağlayan bir Android Jetpack kütüphanesidir. Temelleri açıklıyoruz: Data Binding, findViewById() tekrar kodunu ortadan kaldırır ve veri değiştiğinde UI'yı otomatik olarak günceller. Google'a göre (Android Developers, 2025), Data Binding Android projelerinin %45inde kullanılır ve LiveData veya StateFlow ile kombinasyon halinde manuel abonelik yönetimi olmadan tamamen reaktif bağlama sağlar.

Önemli Noktalar

  • Data Binding — düzen etiketleri aracılığıyla XML düzenlerini veri kaynaklarına bildirimsel olarak bağlamak için Jetpack kütüphanesi.
  • Çift yönlü bağlama — XML'de @={} ile View ve ViewModel arasında otomatik veri senkronizasyonu.
  • @BindingAdapter — standart Data Binding'i genişleten View öznitelikleri için özel setter.
  • Data Binding + LiveData — Observer olmadan reaktivite: LiveData değişiklikleri UI'yı otomatik günceller.
  • Data Binding, derleme zamanında Binding sınıfı (örneğin ActivityMainBinding) oluşturarak View'lara type-safe erişim sağlar.

Android'de Data Binding Nedir?

Data Binding, ilk olarak 2015'te Google I/O'da ortaya çıkan ve Android Gradle Plugin 1.5'te kararlı hale getirilen bir destek kütüphanesidir (Android Jetpack). Activity veya Fragment kodunda findViewById() çağırmadan XML'deki UI bileşenlerini doğrudan düzen içinde veri kaynaklarına (POJO, ViewModel, LiveData) bağlamaya olanak tanır.

Çalışma prensibi: XML düzeni, bir veri türüyle <variable> bildiren <layout> etiketine sarılır. Düzen içinde veriler, süslü parantezler @{} içindeki ifadelerle değiştirilir. Derleme zamanında Android Gradle Plugin, doğru türlerle View'lara doğrudan referanslar ve veri ayarlama yöntemleri içeren bir Binding sınıfı (örneğin ActivityMainBinding) oluşturur.

Android Developers Anketine (2024) göre Data Binding, bağlama mantığını XML'e taşıyarak Activity/Fragment'teki UI kodu miktarını %30–50 oranında azaltır. findViewById() ile ClassCastException gibi yanlış View türüyle ilgili hataların sayısı, tüm türler derleme zamanında kontrol edildiği için sıfıra düşer.

Data Binding vs ViewBinding: Hangisini Seçmeli

ViewBinding, Android Studio 3.6'da (2020) tanıtılan Data Binding'in daha hafif bir alternatifidir. ViewBinding her düzen dosyası için bir Binding sınıfı oluşturur ancak ifadeler, değişkenler ve reaktivite desteği olmadan. Anahtar kriterlere göre karşılaştırma:

KriterData BindingViewBinding
Binding sınıfı oluşturmaEvetEvet
XML ifadeleri (@{})EvetHayır
Çift yönlü bağlamaEvetHayır
Reaktif (LiveData)EvetHayır
@BindingAdapterEvetHayır
Derleme hızıDaha yavaş (ifade işleme)Daha hızlı
KarmaşıklıkYüksekDüşük

Google'ın önerisi (Android Developers, 2025): çoğu proje için ViewBinding yeterlidir — Data Binding'in ek yükü olmadan View'lara type-safe erişim sağlar. Data Binding'i şu durumlarda seçin: (1) XML'den LiveData/StateFlow ile reaktif bağlama, (2) formlar için çift yönlü bağlama, (3) özel öznitelikler için BindingAdapter, (4) biçimlendirme için XML ifadeleri. IT Sectr'de basit ekranlar için ViewBinding, karmaşık formlar ve panolar için Data Binding kullanıyoruz.

Çift Yönlü Bağlama: @{} ve @={}

Tek yönlü bağlama (@{}) verileri kaynaktan (ViewModel) View'e iletir. Çift yönlü bağlama (@={}) verileri her iki yönde senkronize eder: View'deki değişiklikler (metin girişi, Switch değiştirme) kaynağı otomatik olarak günceller.

xml
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="viewModel"
            type="com.example.app.LoginViewModel" />
    </data>

    <LinearLayout ...>
        <!-- Tek yönlü: ViewModel'den TextView'e veri -->
        <TextView
            android:text="@{viewModel.userName}" />

        <!-- Çift yönlü: EditText değişiklikleri → ViewModel, ViewModel → EditText -->
        <EditText
            android:text="@{=viewModel.email}" />

        <CheckBox
            android:checked="@{=viewModel.agreeToTerms}" />
    </LinearLayout>
</layout>

Çift yönlü bağlama için ViewModel'in ObservableField, LiveData veya StateFlow kullanması gerekir. Kullanıcı girişiyle veri değiştiğinde Data Binding otomatik olarak kaynağın setter'ını çağırır. Önemli: çift yönlü bağlama, @InverseBindingAdapter tanımlanmış özniteliklerle çalışır. Android şunlar için yerleşik bağdaştırıcılar sağlar: text, checked, visibility, progress, rating ve diğer standart öznitelikler.

@BindingAdapter: Özel Öznitelikler ve Dönüştürücüler

@BindingAdapter, herhangi bir View özniteliği için özel bağlama mantığı tanımlamaya olanak tanıyan Kotlin uzantı işlevleri için bir ek açıklamadır. Örneğin, XML'de bir URL belirtirken Glide aracılığıyla resim yüklemek veya bir TextView'a bağlanırken tarih biçimlendirmek.

kotlin
// URL ile resim yüklemek için BindingAdapter
@BindingAdapter("imageUrl")
fun ImageView.setImageUrl(url: String?) {
    Glide.with(this.context)
        .load(url)
        .placeholder(R.drawable.placeholder)
        .error(R.drawable.error)
        .into(this)
}

// Birden çok özniteliğe sahip BindingAdapter
@BindingAdapter("visibleGone")
fun View.setVisibleGone(visible: Boolean) {
    visibility = if (visible) View.VISIBLE else View.GONE
}

// Dönüştürücü ile BindingAdapter (formatDate)
@BindingAdapter("formattedDate")
fun TextView.setFormattedDate(timestamp: Long) {
    text = SimpleDateFormat("dd.MM.yyyy", Locale.getDefault()).format(Date(timestamp))
}
xml
<!-- XML'de BindingAdapter kullanımı -->
<ImageView
    imageUrl="@{user.avatarUrl}"
    android:layout_width="48dp"
    android:layout_height="48dp" />

<TextView
    formattedDate="@{message.createdAt}"
    visibleGone="@{message.isVisible}" />

@BindingAdapter birden çok özniteliği (requireAll = true/false) kabul ederek değerlerin birleştirilmesine olanak tanır. Örneğin, @BindingAdapter("imageUrl", "circleCrop") — circleCrop true ise Glide CircleCrop dönüşümünü uygular. Google'a göre (Android Performance, 2024), Data Binding'de Glide ile BindingAdapter, RecyclerView kaydırılırken saniyede 60 kareye kadar işlem yapar çünkü asenkron yükleme UI iş parçacığını engellemez.

LiveData ve StateFlow ile Data Binding

Data Binding, Android Architecture Components 1.0'dan beri LiveData'yı yerel olarak destekler. Düzendeki bir değişken LiveData türündeyse Binding otomatik olarak ona abone olur ve değer değiştiğinde UI'yı günceller. Doğru çalışma için Binding sınıfında LifecycleOwner ayarlanmalıdır: binding.lifecycleOwner = viewLifecycleOwner.

kotlin
// LiveData ile ViewModel
class WeatherViewModel : ViewModel() {
    private val _temperature = MutableLiveData("--")
    val temperature: LiveData<String> get() = _temperature

    val cityName = MutableLiveData("Moskova")
    val weatherIcon = MutableLiveData(R.drawable.ic_sunny)

    fun refresh() {
        viewModelScope.launch {
            _temperature.value = weatherRepository.getTemperature()
        }
    }
}

// Fragment'te:
val binding = FragmentWeatherBinding.inflate(inflater, container, false)
binding.viewModel = weatherViewModel
binding.lifecycleOwner = viewLifecycleOwner  // ← LiveData için gerekli
xml
<layout>
    <data>
        <variable name="viewModel" type="com.example.app.WeatherViewModel" />
    </data>

    <LinearLayout ...>
        <TextView
            android:text="@string/temperature_format(viewModel.temperature)" />
        <TextView android:text="@{viewModel.cityName}" />
        <ImageView
            android:src="@{viewModel.weatherIcon}"
            contentDescription="@{viewModel.cityName}" />
    </LinearLayout>
</layout>

Data Binding, lifecycle 2.5.0'dan itibaren Flow.asLiveData() veya doğrudan dönüştürme yoluyla StateFlow'u destekler. Data Binding'de StateFlow kullanırken binding.lifecycleOwner aracılığıyla yaşam döngüsünün ayarlandığından emin olun. LifecycleOwner ayarlanmazsa LiveData/StateFlow UI'yı güncellemez çünkü Binding abonenin ne zaman aktif olduğunu bilmez.

Kod Örnekleri: Kotlin ve XML'de Data Binding

Örnek 1: Data Binding ile Profil Ekranı

Avatar, ad, biyografi ve düzenleme düğmesi içeren tam bir profil ekranı. ViewModel reaktivite için ObservableField kullanır.

xml
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <variable name="profile" type="com.example.app.ProfileViewModel" />
    </data>

    <androidx.constraintlayout...>
        <ImageView
            app:imageUrl="@{profile.avatarUrl}"
            android:contentDescription="@{profile.name}" />

        <TextView
            android:text="@{profile.name}"
            android:textStyle="bold" />

        <TextView
            android:text="@{profile.bio}"
            android:visibility="@{profile.hasBio ? View.VISIBLE : View.GONE}" />

        <Button
            android:onClick="@{() -> profile.onEdit()}"
            android:text="@string/edit" />
    </androidx.constraintlayout...>
</layout>
kotlin
class ProfileViewModel : ViewModel() {
    val name = ObservableField("Anna Petrova")
    val bio = ObservableField("Android geliştirici, 5 yıllık deneyim")
    val avatarUrl = ObservableField("https://example.com/avatar.jpg")
    val hasBio = ObservableBoolean(true)

    fun onEdit() {
        // Profil düzenleme mantığı
    }
}

// Fragment'te:
val binding = FragmentProfileBinding.inflate(inflater, container, false)
binding.profile = profileViewModel
binding.lifecycleOwner = viewLifecycleOwner

Örnek 2: Çift Yönlü Bağlama ile Giriş Formu

Alan doğrulaması ve giriş düğmesi olan bir giriş formu. Çift yönlü bağlama (@={}) kullanıcı girişini ViewModel ile senkronize eder.

xml
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable name="login" type="com.example.app.LoginViewModel" />
    </data>

    <LinearLayout ...>
        <TextInputLayout>
            <TextInputEditText
                android:text="@{=login.email}"
                android:hint="@string/email_hint" />
        </TextInputLayout>

        <TextInputLayout>
            <TextInputEditText
                android:text="@{=login.password}"
                android:inputType="textPassword" />
        </TextInputLayout>

        <Button
            android:onClick="@{() -> login.onLogin()}"
            android:enabled="@{login.isValid}"
            android:text="@string/login" />

        <ProgressBar
            android:visibility="@{login.isLoading ? View.VISIBLE : View.GONE}" />
    </LinearLayout>
</layout>

XML'de ifadeler kullanılır: düğme durumu (etkin/devre dışı) için @{login.isValid}, yükleme göstergesi için @{login.isLoading ? View.VISIBLE : View.GONE}, çift yönlü senkronizasyon için @{=login.email}. Tüm doğrulama mantığı ViewModel'de yaşar; View yalnızca durumu görüntüler. Google'a göre (Android Guide, 2025) bu yaklaşım UI mantığı hatalarının sayısını %50–60 oranında azaltır.

Sıkça Sorulan Sorular

Data Binding Compose ile kullanılabilir mi?

Hayır, Jetpack Compose kendi reaktivite mekanizmasına (Composable işlevler + State) sahip bağımsız bir UI sistemidir. Data Binding yalnızca XML düzenleri için tasarlanmıştır ve Compose ile uyumlu değildir. XML'den Compose'a geçiş yaparken Data Binding kullanılmaz — bunun yerine mutableStateOf(), collectAsState() ve remember uygulanır. Data Binding yalnızca XML düzenlerini koruyan projeler için geçerliliğini korur.

Data Binding findViewById'den daha yavaş mı?

İlk bağlama aşamasında Data Binding, ID'ye göre View araması yapar (findViewById gibi). Fark kullanıcı için fark edilemez: 20–30 View içeren tipik bir ekran 1–3 ms içinde bağlanır. Data Binding'in ana ek yükü derleme zamanındadır (ifade işleme). Çalışma zamanında çoğu ekran için Data Binding ve findViewById arasında fark yoktur. Binlerce öğeli RecyclerView için ViewBinding, daha az oluşturulan kod nedeniyle daha hızlı olabilir.

Data Binding hatası nasıl hata ayıklanır?

Data Binding ifadeleri derleme zamanında koda derler — hatalar Build Output'da XML satırı belirtilerek Compilation errors olarak görünür. Tipik hatalar: yanlış değişken türü, null güvenlik sorunları (varsayılan değerler için ?? kullanın), sınıf içe aktarma eksikliği. build.gradle (app)'de buildFeatures.dataBinding = true etkinleştirin ve <layout>'un XML kök etiketi olduğunu doğrulayın. Çalışma zamanı ifadelerinde hata ayıklamak için BindingAdapter'da BindingConversion ve günlük kaydı kullanın.

BindingConversion nedir?

@BindingConversion, Data Binding ifadelerinde türleri otomatik olarak dönüştüren statik yöntemler için bir ek açıklamadır. Örneğin, Color Int'i ColorDrawable'a dönüştürme: @BindingConversion fun colorToDrawable(color: Int): ColorDrawable = ColorDrawable(color). Bundan sonra android:background="@{color.red}" otomatik olarak çalışacaktır. BindingConversion'lar küreseldir — projedeki tüm Binding ifadelerine uygulanır.

Release derlemeleri için Data Binding devre dışı bırakılmalı mı?

Hayır, Data Binding release derlemelerinde debug'da olduğu gibi çalışır. ProGuard/R8 optimizasyonu, Binding sınıfları doğrudan kullanılmazsa bunları kaldırabilir — kural ekleyin: -keep class * extends android.databinding.ViewDataBinding { *; }. Android Gradle Plugin 7.0'dan itibaren R8, ek kurallar olmadan Data Binding'i doğru şekilde işler. Release için Data Binding'i devre dışı bırakmak performansı artırmaz ancak onu kullanan tüm ekranları bozar.

Özet

  • Data Binding@{} ve @={} ifadeleriyle XML'i verilere bildirimsel olarak bağlamak için Jetpack kütüphanesi.
  • Type-safe Binding sınıfları oluşturur, findViewById() ve ClassCastException'ı ortadan kaldırır.
  • ViewBinding — ifadeler olmadan hafif alternatif; reaktif ve karmaşık UI'lar için Data Binding'i seçin.
  • Çift yönlü bağlama @={} — formlar için otomatik View ↔ ViewModel senkronizasyonu.
  • @BindingAdapter — özel öznitelikler (resim yükleme, biçimlendirme, görünürlük).
  • Data Binding, lifecycleOwner aracılığıyla LiveData ve StateFlow'u yerel olarak destekler.
  • Data Binding, UI kodunu %30–50 azaltır ve bağlama hatalarını sıfıra indirir.

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun