Data Binding — əsaslar, Android-də ikitərəfli bağlama

Müəllif: IT Sectr Dərc olunub: 2026-02-20 Oxuma vaxtı: 8 dəq

Data Binding — Android Jetpack kitabxanası, XML layoutlarından UI komponentlərini deklarativ sintaksis vasitəsilə tətbiq kodundakı data mənbələri ilə birləşdirir. Əsasları izah edirik: Data Binding findViewById() şablon kodunu aradan qaldırır və data dəyişdikdə UI-nı avtomatik yeniləməyə imkan verir. Google məlumatlarına görə (Android Developers, 2025), Data Binding Android layihələrinin 45%-də istifadə olunur və LiveData və ya StateFlow ilə birlikdə əl ilə abunə idarəsi olmadan tam reaktiv bağlama təmin edir.

Əsas məqamlar

  • Data Binding — XML layoutlarını layout teqləri vasitəsilə data mənbələri ilə deklarativ bağlamaq üçün Jetpack kitabxanası.
  • İkitərəfli bağlama — View və ViewModel arasında XML-də @={} vasitəsilə avtomatik data sinxronizasiyası.
  • @BindingAdapter — View atributları üçün xüsusi setter, standart Data Binding-i genişləndirməyə imkan verir.
  • Data Binding + LiveData — Observer olmadan reaktivlik: LiveData dəyişiklikləri UI-nı avtomatik yeniləyir.
  • Data Binding kompilasiya mərhələsində Binding sinfi (məsələn, ActivityMainBinding) yaradaraq View-ə type-safe giriş təmin edir.

Android-də Data Binding nədir?

Data Binding — 2015-ci ildə Google I/O-da təqdim edilmiş və Android Gradle Plugin 1.5-də sabitləşmiş dəstək kitabxanasıdır (Android Jetpack). O, UI komponentlərini XML-də Activity və ya Fragment kodunda findViewById() çağırmadan birbaşa layout daxilində data mənbələri (POJO, ViewModel, LiveData) ilə bağlamağa imkan verir.

İş prinsipi: XML layout <layout> teqinə bükülür, orada data tipi ilə <variable> elan edilir. Layout daxilində data əyri mötərizələrdə ifadələr vasitəsilə yerləşdirilir @{}. Kompilasiya mərhələsində Android Gradle Plugin düzgün tiplərlə View-ə birbaşa istinadlar və data qurma metodları olan Binding sinfi (məsələn, ActivityMainBinding) yaradır.

Android Developers sorğusuna görə (2024), Data Binding bağlama məntiqini XML-ə köçürməklə Activity/Fragment-də UI kodunun həcmini 30–50% azaldır. Yanlış View tipi ilə bağlı səhvlərin sayı (findViewById()-də ClassCastException) sıfıra enir, çünki bütün tiplər kompilasiya mərhələsində yoxlanılır.

Data Binding vs ViewBinding: nə seçməli

ViewBinding — Android Studio 3.6-da (2020) ortaya çıxmış Data Binding-in daha yüngül alternatividir. ViewBinding hər layout faylı üçün Binding sinfi yaradır, lakin ifadələr, dəyişənlər və reaktivlik dəstəyi olmadan. Əsas meyarlara görə müqayisə:

MeyarData BindingViewBinding
Binding sinfinin yaradılmasıBəliBəli
XML-də ifadələr (@{})BəliXeyr
İkitərəfli bağlamaBəliXeyr
Reaktiv (LiveData)BəliXeyr
@BindingAdapterBəliXeyr
Kompilasiya sürətiDaha yavaş (ifadələrin işlənməsi)Daha sürətli
MürəkkəblikYüksəkAşağı

Google tövsiyəsi (Android Developers, 2025): əksər layihələr üçün ViewBinding kifayətdir — Data Binding-in əlavə yüklənməsi olmadan View-ə type-safe giriş təmin edir. Data Binding-i seçin, əgər lazımdırsa: (1) XML-dən LiveData/StateFlow ilə reaktiv bağlama, (2) formalar üçün ikitərəfli bağlama, (3) xüsusi atributlar üçün BindingAdapter, (4) formatlaşdırma üçün XML-də ifadələr. IT Sectr-də sadə ekranlar üçün ViewBinding, mürəkkəb formalar və panellər üçün Data Binding istifadə edirik.

İkitərəfli bağlama: @{} və @={}

Tək tərəfli bağlama (@{}) data mənbədən (ViewModel) View-ə ötürür. İkitərəfli bağlama (@={}) datanı hər iki istiqamətdə sinxronlaşdırır: View-də dəyişiklik (mətn daxil etmə, Switch keçidi) avtomatik olaraq mənbəyi yeniləyir.

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

    <LinearLayout ...>
        <!-- Bir tərəfli: ViewModel-dən TextView-ə data -->
        <TextView
            android:text="@{viewModel.userName}" />

        <!-- İkitərəfli: EditText dəyişiklikləri → ViewModel, ViewModel → EditText -->
        <EditText
            android:text="@{=viewModel.email}" />

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

İkitərəfli bağlama üçün ViewModel ObservableField, LiveData və ya StateFlow istifadə etməlidir. İstifadəçi girişi ilə data dəyişdikdə Data Binding avtomatik olaraq mənbənin setterini çağırır. Vacib: ikitərəfli bağlama @InverseBindingAdapter təyin edilmiş atributlarla işləyir. Android daxili adapterlər təqdim edir: text, checked, visibility, progress, rating və digər standart atributlar üçün.

@BindingAdapter: xüsusi atributlar və çeviricilər

@BindingAdapter — Kotlin extension funksiyaları üçün annotasiya, istənilən View atributu üçün xüsusi bağlama məntiqini təyin etməyə imkan verir. Məsələn, XML-də URL göstərildikdə Glide vasitəsilə şəkil yükləmək və ya TextView ilə bağlamada tarixi formatlaşdırmaq.

kotlin
// URL üzrə şəkil yükləmək üçün BindingAdapter
@BindingAdapter("imageUrl")
fun ImageView.setImageUrl(url: String?) {
    Glide.with(this.context)
        .load(url)
        .placeholder(R.drawable.placeholder)
        .error(R.drawable.error)
        .into(this)
}

// Çoxlu atributlarla BindingAdapter
@BindingAdapter("visibleGone")
fun View.setVisibleGone(visible: Boolean) {
    visibility = if (visible) View.VISIBLE else View.GONE
}

// Çevirici ilə BindingAdapter (formatDate)
@BindingAdapter("formattedDate")
fun TextView.setFormattedDate(timestamp: Long) {
    text = SimpleDateFormat("dd.MM.yyyy", Locale.getDefault()).format(Date(timestamp))
}
xml
<!-- XML-də BindingAdapter istifadəsi -->
<ImageView
    imageUrl="@{user.avatarUrl}"
    android:layout_width="48dp"
    android:layout_height="48dp" />

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

@BindingAdapter çoxlu atribut qəbul edə bilər (requireAll = true/false), bu da dəyərləri birləşdirməyə imkan verir. Məsələn, @BindingAdapter("imageUrl", "circleCrop") — əgər circleCrop true-dirsə, Glide CircleCrop transformasiyasını tətbiq edir. Google məlumatlarına görə (Android Performance, 2024), Data Binding-də Glide ilə BindingAdapter RecyclerView sürüşdürməsində saniyədə 60 kadra qədər işləyir, çünki asinxron yükləmə UI threadini bloklamır.

Data Binding LiveData və StateFlow ilə

Data Binding LiveData-nı native dəstəkləyir Android Architecture Components 1.0 versiyasından. Layoutda dəyişən LiveData tipinə malikdirsə, Binding avtomatik olaraq ona abunə olur və qiymət dəyişdikdə UI-nı yeniləyir. Düzgün işləmə üçün Binding sinfində LifecycleOwner təyin edilməlidir: binding.lifecycleOwner = viewLifecycleOwner.

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

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

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

// Fragment-də:
val binding = FragmentWeatherBinding.inflate(inflater, container, false)
binding.viewModel = weatherViewModel
binding.lifecycleOwner = viewLifecycleOwner  // ← LiveData üçün məcburi
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 StateFlow-u lifecycle 2.5.0-dan Flow.asLiveData() və ya birbaşa konvertasiya vasitəsilə dəstəkləyir. Data Binding-də StateFlow istifadə edərkən binding.lifecycleOwner vasitəsilə həyat dövrünün təyin olunduğuna əmin olun. LifecycleOwner təyin olunmadan LiveData/StateFlow UI-nı yeniləməyəcək, çünki Binding abunəçinin nə vaxt aktiv olduğunu bilmir.

Kod nümunələri: Kotlin və XML-də Data Binding

Nümunə 1: Data Binding ilə profil ekranı

Avatar, ad, bio və redaktə düyməsi ilə tam profil ekranı. ViewModel reaktivlik üçün ObservableField istifadə edir.

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-developer, 5 il təcrübə")
    val avatarUrl = ObservableField("https://example.com/avatar.jpg")
    val hasBio = ObservableBoolean(true)

    fun onEdit() {
        // Profil redaktə məntiqi
    }
}

// Fragment-də:
val binding = FragmentProfileBinding.inflate(inflater, container, false)
binding.profile = profileViewModel
binding.lifecycleOwner = viewLifecycleOwner

Nümunə 2: İkitərəfli bağlama ilə giriş forması

Sahə validasiyası və giriş düyməsi ilə giriş forması. İkitərəfli bağlama (@={}) istifadəçi girişini ViewModel ilə sinxronlaşdırır.

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-də ifadələr istifadə olunur: düymə vəziyyəti üçün @{login.isValid} (aktiv/aktiv deyil), yükləmə göstəricisi üçün @{login.isLoading ? View.VISIBLE : View.GONE}, ikitərəfli sinxronizasiya üçün @{=login.email}. Bütün validasiya məntiqi ViewModel-də yaşayır, View yalnız vəziyyəti göstərir. Google məlumatlarına görə (Android Guide, 2025), bu yanaşma UI məntiqindəki səhvlərin sayını 50–60% azaldır.

Tez-tez verilən suallar

Data Binding-dən Compose ilə istifadə etmək olar?

Xeyr, Jetpack Compose öz reaktivlik mexanizmi (Composable funksiyaları + State) olan müstəqil UI sistemidir. Data Binding yalnız XML layoutları üçün nəzərdə tutulub və Compose ilə uyğun deyil. XML-dən Compose-a miqrasiya zamanı Data Binding istifadə edilmir — onun əvəzinə mutableStateOf(), collectAsState()remember tətbiq olunur. Data Binding yalnız XML layoutlarını qoruyan layihələr üçün aktual qalır.

Data Binding findViewById-dən yavaşdır?

İlk bağlama mərhələsində Data Binding View-i ID ilə axtarır (findViewById kimi). Fərq istifadəçi üçün nəzərə çarpmır: 20–30 View olan tipik ekran 1–3 ms-də bağlanır. Data Binding-in əsas əlavə yüklənməsi kompilasiya mərhələsindədir (ifadələrin işlənməsi). Runtime-da Data Binding və findViewById arasında fərq əksər ekranlar üçün yoxdur. Minlərlə elementi olan RecyclerView üçün ViewBinding daha az kod yaradıldığından daha sürətli ola bilər.

Data Binding səhvini necə debug etməli?

Data Binding ifadələri qurma mərhələsində koda kompilə edir — səhvlər Build Output-da XML sətri göstərilməklə Compilation errors kimi göstərilir. Tipik səhvlər: yanlış dəyişən tipi, null-təhlükəsizlik (default dəyərlər üçün ?? istifadə edin), sinif importunun olmaması. build.gradle (app)-də buildFeatures.dataBinding = true aktiv edin və <layout>-un XML-in kök teqi olduğunu yoxlayın. Runtime ifadələrini debug etmək üçün BindingConversion və BindingAdapter-də loglamadan istifadə edin.

BindingConversion nədir?

@BindingConversion — statik metodlar üçün annotasiya, Data Binding ifadələrində tipləri avtomatik çevirir. Məsələn, Color Int-i ColorDrawable-a çevirmək: @BindingConversion fun colorToDrawable(color: Int): ColorDrawable = ColorDrawable(color). Bundan sonra android:background="@{color.red}" avtomatik işləyəcək. BindingConversion qlobaldır — layihədəki bütün Binding ifadələrinə tətbiq olunur.

Release qurması üçün Data Binding-i söndürmək lazımdır?

Xeyr, Data Binding release qurmasında debugda olduğu kimi işləyir. ProGuard/R8 optimallaşdırması Binding siniflərini silə bilər, əgər birbaşa istifadə edilmirsə — qayda əlavə edin: -keep class * extends android.databinding.ViewDataBinding { *; }. Android Gradle Plugin 7.0-dan başlayaraq, R8 Data Binding-i əlavə qaydalar olmadan düzgün emal edir. Release üçün Data Binding-in söndürülməsi performans artımı vermir, lakin ondan istifadə edən bütün ekranları sındırır.

Nəticə

  • Data Binding — XML-i @{}@={} ifadələri vasitəsilə data ilə deklarativ bağlamaq üçün Jetpack kitabxanası.
  • Type-safe Binding sinifləri yaradır, findViewById() və ClassCastException-u aradan qaldırır.
  • ViewBinding — ifadələrsiz yüngül alternativ; reaktiv və mürəkkəb UI üçün Data Binding seçin.
  • İkitərəfli bağlama @={} — formalar üçün View ↔ ViewModel avtomatik sinxronizasiyası.
  • @BindingAdapter — xüsusi atributlar (şəkil yükləmə, formatlaşdırma, görünürlük).
  • Data Binding LiveData və StateFlow-u lifecycleOwner vasitəsilə native dəstəkləyir.
  • Data Binding UI kodunu 30–50% azaldır və bağlama səhvlərinin sayını sıfıra endirir.

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun