Two-Way Binding: nedir, Android ve iOS'ta çift yönlü veri bağlama

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

Two-Way Bindingin ne olduğunu öğrenin — mobil uygulamalarda model ve görünümü otomatik olarak senkronize eden çift yönlü veri bağlama. findViewById aracılığıyla manuel UI güncellemesinin aksine, bağlama mekanizması kullanıcı girişi değiştiğinde modeli ve veri değiştiğinde görünümü günceller. Google I/O 2024'e göre, bağlama Android ve iOS projelerinde kalıplaşmış UI kodunu %30–50 oranında azaltır. Bu yaklaşım Jetpack Compose ve SwiftUI'den Flutter ve React Native'e kadar çerçevelerde kullanılır.

Önemli Noktalar

  • Two-Way Binding — model (ViewModel) ve görünüm arasında her iki yönde verileri otomatik olarak senkronize eden bir mekanizmadır.
  • Android'de DataBinding'de @BindingAdapter ve @= ile, iOS'ta ise SwiftUI'de @Binding ile uygulanır.
  • Google'a göre, DataBinding findViewById ile manuel bağlamaya kıyasla UI kodu hacmini %30–50 oranında azaltır.
  • Ana tehlike, yanlış yapılandırılmış değişiklik dinleyicilerinin neden olduğu sonsuz güncelleme döngüleridir.
  • Modern geliştirmede, açık olaylarla tek yönlü veri akışı (UDF) tercih edilir ve Two-Way Binding, giriş formları için seçici olarak uygulanır.

Two-Way Binding Nedir?

Two-Way Binding (çift yönlü veri bağlama) — veri modelindeki değişikliklerin otomatik olarak kullanıcı arayüzüne yansıdığı ve UI'daki değişikliklerin modeli hemen güncellediği bir mimari mekanizmadır. Verilerin yalnızca modelden görünüme aktığı tek yönlü bağlamanın aksine, çift yönlü bağlama her güncellemeyi manuel olarak kodlamadan kapalı bir senkronizasyon döngüsü oluşturur.

Android Developers Blog'a (2023) göre, 2015'te tanıtılan DataBinding kütüphanesi, ticari Android uygulamalarının %42'sinde kullanılmaktadır. Mekanizma özellikle metin alanları, anahtarlar, kaydırıcılar ve onay kutuları gibi giriş formlarında talep görmektedir; burada kullanıcı girişi anında modele ve programatik değişiklikler UI'ya yansımalıdır. Tüm bu senaryolarda, geliştirici bir "dinleyici + ayarlayıcı" çifti yerine bir bağlama yazar.

IT Sectr'de, 2017'den beri projelerde çift yönlü bağlama uyguladık ve bilinçli olarak kullanılmasını öneriyoruz: basit giriş alanları için, ancak bağımlılıkları olan karmaşık durumlar için değil.

Çift Yönlü Bağlama Nasıl Çalışır?

Two-Way Binding mekanizması üç temel öğe üzerine kuruludur: gözlemlenebilir alan (observable), değişiklik dinleyicisi ve ters senkronizasyon mekanizması. Bir kullanıcı EditText alanına metin yazdığında, sistem TextWatcher olayını yakalar, yeni değeri bağlı değişkene yazar ve değişken koddan değiştiyse UI'ya yeniden çizim yapmasını bildirir.

Perde arkasında, Android DataBinding kütüphanesi derleme zamanında tüm bağlama mantığını içeren bir Binding sınıfı oluşturur. @={variable} özniteliğine sahip her View için, geçersiz kılma ile bir setter + getter çifti oluşturulur. SwiftUI'de, @Binding propertyWrapper Combine mekanizması aracılığıyla değeri senkronize ederek benzer bir iş yapar. SwiftUI, @Published özellikleri aracılığıyla değişiklikleri izler ve bağlı değişkendeki herhangi bir değişiklikte View'ı otomatik olarak yeniden çizer.

WWDC Session 10033'e (2023) göre, SwiftUI'deki @Binding mekanizması, giriş alanlarını senkronize ederken saniyede 60 kareye kadar işlem yapabilir ve bu da onu gecikmesiz etkileşimli formlar için uygun hale getirir. Her iki çerçevede de Two-Way Binding, Observer deseni üzerinde sözdizimsel şekerdir ve abonelik ile bildirimi otomatikleştirir.

Android'de Two-Way Binding: DataBinding ve Jetpack Compose

Android'de çift yönlü bağlama iki varyasyonda mevcuttur: @={} özniteliği aracılığıyla klasik XML DataBinding ve çift yönlü durum referansları aracılığıyla Jetpack Compose. Her iki yaklaşım da aynı sorunu — UI ve modeli senkronize etme — çözer ancak sözdizimi ve uygulama kapsamı açısından farklılık gösterir.

@BindingAdapter ve @= ile DataBinding

XML işaretlemesinde, çift yönlü bağlama @={variable.property} sözdizimi ile gösterilir — süslü parantezler içindeki eşittir işareti onu tek yönlü @{variable}'den ayırır. Özel Views için ters öznitelikle birlikte @BindingAdapter ek açıklaması gereklidir.

XML
<layout>
    <data>
        <variable name="viewModel" type="com.example.LoginViewModel" />
    </data>
    <EditText
        android:text="@{viewModel.email}" />
    <CheckBox
        android:checked="@{viewModel.agreeToTerms}" />
</layout>

Örnek, e-posta ve onay kutusuyla basit bir form gösterir — her iki alan da çift yönlü bağlama kullanır, bu da Activity kodunda TextWatcher ve OnCheckedChangeListener yazma ihtiyacını ortadan kaldırır. Kullanıcı metni değiştirdiğinde, viewModel.email alanı otomatik olarak güncellenir.

Kotlin
@BindingAdapter("app:rating")
fun RatingBar.setRating(rating: Float) {
    if (rating != this.rating) {
        this.rating = rating
    }
}

@InverseBindingAdapter("app:rating")
fun RatingBar.getRating(): Float = this.rating

@BindingAdapter("app:ratingAttrChanged")
fun RatingBar.setListeners(
    listener: InverseBindingListener?
) {
    this.onRatingBarChangeListener =
        RatingBar.OnRatingBarChangeListener { _, _, _ -> listener?.onChange() }
}

RatingBar için özel bir BindingAdapter, DataBinding kütüphanesinin View'dan değeri nasıl okuyacağını (ters geri bildirim) ve View'a nasıl yazacağını (doğrudan bağlama) bilmesi için bir çift ek açıklama — @BindingAdapter ve @InverseBindingAdapter — kullanır. AttrChanged sonekine sahip üçüncü bağdaştırıcı, kullanıcı tarafından başlatılan değer değişikliklerini sisteme bildirir.

Jetpack Compose'da Two-Way Binding

Jetpack Compose @={} sözdizimini desteklemez ancak mutableStateOf ve açık setter işlevi iletme yoluyla benzer bir mekanizma sağlar. Compose'da çift yönlü bağlama, alt bileşenlere State ve bir geri çağırma işlevi (value, onValueChange) iletilerek oluşturulur.

Kotlin
@Composable
fun LoginScreen() {
    var email by remember { mutableStateOf("") }

    OutlinedTextField(
        value = email,
        onValueChange = { email = it },
        label = { Text("E-posta") }
    )
}

@Composable
fun CustomRatingBar(
    rating: Float,
    onRatingChange: (Float) -> Unit
) {
    Slider(
        value = rating,
        onValueChange = onRatingChange,
        valueRange = 0f..5f
    )
}

Compose'da çift yönlü iletişim, state + callback çifti aracılığıyla öykünülür — üst öğe geçerli değeri ve bir güncelleme işlevini iletir, alt bileşen kullanıcı etkileşiminde callback'i çağırır. Bu yaklaşım, veri akışı yönünü açıkça gösterir ve örtük DataBinding senkronizasyonuna kıyasla hata ayıklamayı basitleştirir.

iOS'ta Two-Way Binding: SwiftUI'de @Binding

SwiftUI'de çift yönlü bağlama, üst View'e ait bir veri kaynağına okuma-yazma referansı oluşturan @Binding propertyWrapper aracılığıyla uygulanır. @Binding değeri kendi başına depolamaz — üst öğenin @State veya @StateObject'i aracılığıyla okur ve yazar.

Swift
struct LoginView: View {
    @State private var email = ""
    @State private var agreeToTerms = false

    var body: some View {
        Form {
            TextField("Email", text: $email)
            Toggle("Şartları kabul ediyorum", isOn: $agreeToTerms)
            ChildRatingView(rating: $rating)
        }
    }
}

struct ChildRatingView: View {
    @Binding var rating: Double

    var body: some View {
        Slider(value: $rating, in: 0...5)
    }
}

Bir değişken adından önceki $ sembolü bir Binding referansı oluşturur: $email'in türü Binding'dır, String değil. SwiftUI, TextField'deki metin değişikliklerini Combine mekanizması aracılığıyla email özelliğinin güncellenmesine otomatik olarak bağlar. Üst View, @State'ine bir Binding'i alt bileşene iletir ve temsilciler veya callback'ler olmadan herhangi bir hiyerarşi seviyesinden durum değişikliğine izin verir.

Apple WWDC 2023'e göre, SwiftUI yeniden çizimleri en aza indirmek için bir fark bulma algoritması kullanır: @Binding değeri değişirse ancak View bu değere bağlı değilse, yeniden çizim gerçekleşmez. Bu, UIKit ile karşılaştırılabilir performans sağlar (ProMotion ekranlarda 120 FPS'ye kadar).

Two-Way Binding vs UDF: Ne Zaman Ne Seçilmeli

Çift yönlü bağlama ile tek yönlü veri akışı (UDF) arasındaki seçim, mobil geliştirmedeki kilit mimari kararlardan biridir. Two-Way Binding, yerel form durumları için idealdir ve kullanıcının her adımının ek kod olmadan hemen modele yansıması gerektiği durumlarda kullanılır. UDF, değişikliklerin öngörülebilirliğinin geliştirme hızından daha önemli olduğu genel uygulama durumu için tercih edilir.

KriterTwo-Way BindingUDF
Formdaki kod hacmi1 satır (@={} özniteliği)5–7 satır (State, Intent, Reducer)
Veri akışı hata ayıklamaZor (kim değiştirdi — UI mı kod mu?)Kolay (tüm değişiklikler Intent ile)
PerformansYüksek (yerel senkronizasyon)Orta (Reducer + Redux katmanı)
ÖlçeklenebilirlikKarmaşık formlarda doğrulama ile düşerEkran sayısıyla artar
Durum öngörülebilirliğiDüşük (döngülerden yan etkiler)Yüksek (reducer tek gerçek kaynağıdır)

Öneri: Karmaşık doğrulama olmadan 3–5 alanlı formlarda basit giriş alanları (metin, onay kutuları, anahtarlar) için Two-Way Binding kullanın. Genel durum, ağ istekleri ve bağımlı alanlar içeren ekranlar için açık olay işleme ile tek yönlü akışlı UDF kullanın. IT Sectr'de her iki yaklaşımı birleştiriyoruz: formların içinde Two-Way Binding, gezinme ve iş mantığı için UDF.

Çift Yönlü Bağlamada Sık Yapılan Hatalar

Sonsuz güncelleme döngüsü — Two-Way Binding kullanırken en yaygın sorun. Döngü, bir model değişikliğinin bir UI güncellemesini tetiklemesi ve bunun da modeli tekrar değiştirmesiyle oluşur. DataBinding'de bu, @InverseBindingAdapter'deki getter'ın bir setter çağrısından hemen sonra yeni bir değer döndürmesi durumunda gerçekleşir. Çözüm, geri yazmadan önce değerin değişip değişmediğini kontrol etmektir (koruma koşulu).

İkinci yaygın hata, hesaplanan alanları bağlamaktır. Bir alan başka bir alana bağlıysa (örneğin, toplam maliyet = fiyat × miktar), çift yönlü bağlama tutarsız bir duruma yol açabilir. Örneğin, kullanıcı miktarı değiştirir, bu bir maliyet yeniden hesaplamasını tetikler ve bu da miktarı tekrar değiştirir. Hesaplanan alanlar için Flow veya Combine ile tek yönlü bağlama kullanın.

Üçüncü hata, LifecycleOwner olmadan Observable alanları bağlamaktır. Android DataBinding'de, bağlamaya bir LifecycleOwner iletilmelidir, aksi takdirde Activity yok edildiğinde gözlemciler temizlenmez ve bu da bellek sızıntılarına yol açar. Fragment'larda her zaman viewLifecycleOwner'ı ve Activity'de this'i iletin.

Google Issue Tracker'a (2024) göre, DataBinding hata raporlarının yaklaşık %15'i döngüsel güncellemelerle ilgilidir. Teşhis için Android Studio Layout Inspector'ı kullanın — ekrandaki tüm bağlamaların geçerli değerlerini gösterir ve sonsuz döngünün kaynağını bulmayı kolaylaştırır.

Sıkça Sorulan Sorular

Çift yönlü bağlama tek yönlü bağlamadan nasıl farklıdır?

Tek yönlü bağlama (One-Way Binding) verileri yalnızca modelden görünüme aktarır — model değiştiğinde UI güncellenir, ancak kullanıcı girişi modeli doğrudan değiştirmez. Two-Way Binding verileri her iki yönde senkronize eder: UI'daki bir değişiklik otomatik olarak modeli günceller ve bunun tersi de geçerlidir. DataBinding sözdiziminde fark, @{} (Tek Yönlü) ve @={} (Çift Yönlü) ile belirtilir.

Two-Way Binding ne zaman kullanılmamalıdır?

Bağımlı alanlar, hesaplanan değerler veya özel doğrulama içeren karmaşık formlar için çift yönlü bağlama kullanmayın — bu senaryolarda veri akışı tahmin edilemez hale gelir. Ayrıca, her öğenin bağlaması olan çok sayıda öğe içeren RecyclerView gibi listelerde de kaçının: çok sayıda gözlemci nedeniyle performans düşer. UDF, tek yönlü akış ve Intent tabanlı olay işleme ile daha iyi ölçeklenir.

Jetpack Compose çift yönlü bağlamayı destekliyor mu?

Jetpack Compose'un yerleşik @={} sözdizimi yoktur, ancak çift yönlü senkronizasyon State + callback (onValueChange) çifti aracılığıyla uygulanır. Üst öğe geçerli değeri (State) ve bir güncelleme işlevini iletir, alt bileşen değişiklikte callback'i çağırır. Bu örtük değil, açık bağlamadır — veri akışı görünür ve izlenebilir kalır.

DataBinding'de sonsuz döngü nasıl hata ayıklanır?

DataBinding'de döngüleri hata ayıklamak için Android Studio Layout Inspector kullanın — ekrandaki tüm bağlı değişkenlerin geçerli değerlerini gösterir. @InverseBindingAdapter'ye günlük ekleyin ve getter'ın yeni yazılan değerden farklı bir değer döndürüp döndürmediğini kontrol edin. Standart çözüm, geri yazmadan önce bir koruma koşuludur: if (newValue != currentValue).

Flutter'da Two-Way Binding var mı?

Flutter'da yerleşik çift yönlü bağlama yoktur, ancak TextEditingController ve onChanged callback'inin bir kombinasyonu aracılığıyla öykünülebilir. StatefulWidget için geliştirici, denetleyici değişikliklerine manuel olarak abone olur ve modeli günceller. Provider ve Riverpod'da, çift yönlü senkronizasyon Selector aracılığıyla oluşturulur; bu, model değiştiğinde widget'ı yeniden oluşturur ve kullanıcı girişinde bir callback çağırır.

Özet

  • Two-Way Binding — model ve görünüm arasında otomatik çift yönlü senkronizasyon mekanizmasıdır, dinleyicileri ve ayarlayıcıları manuel olarak yazma ihtiyacını ortadan kaldırır.
  • Android'de @={} sözdizimi ve @BindingAdapter/@InverseBindingAdapter ek açıklamalarıyla DataBinding aracılığıyla uygulanır.
  • iOS'ta SwiftUI, üst öğenin @State'ine okuma-yazma referansı oluşturan @Binding propertyWrapper'ı sağlar.
  • DataBinding, UI kodu hacmini %30–50 oranında azaltır, ancak sonsuz döngüler ortaya çıktığında hata ayıklamayı zorlaştırır.
  • 3–5 alanlı formlar için Two-Way Binding etkilidir; genel durum ve karmaşık doğrulama için UDF'yi seçin.
  • Jetpack Compose'da çift yönlü iletişim, State + onValueChange callback'i aracılığıyla öykünülür ve açık veri akışını korur.
  • Ana riskler döngüsel güncellemeler, hesaplanan alanların bağlanması ve LifecycleOwner olmadığında bellek sızıntılarıdır.

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