View Binding

View binding, view ile etkileşime giren kodu daha kolay yazmanıza olanak tanıyan bir özelliktir. View binding etkinleştirildiğinde, her XML layout dosyası için bir binding sınıfı oluşturulur. Böylece bu layout içerisinde bulunan viewlerin sahip oldukları ID üzerinden doğrudan erişim sağlanabilir. View bindingi etkinleştirdikten sonra activity_main.xml adında bir layout oluşturduğunuzu varsayalım. Arkaplanda otomatik olarak ActivityMainBinding.kt dosyası oluşturulur.

View binding, findViewById‘nin yerini alır.

Kurulum

View bindingi etkinleştirmek için build.gradle dosyasında viewBinding build seçeneğini true olarak ayarlayın.

android {
    ...
    buildFeatures {
        viewBinding true
    }
}

Eğer binding sınıfının oluşmasını istemiyorsanız tools:viewBindingIgnore="true" niteliğini ekleyebilirsiniz.

<LinearLayout
        ...
        tools:viewBindingIgnore="true" >
    ...
</LinearLayout>

Kullanım

Projede view binding etkinleştirilmişse, her layout dosyası için binding sınıfı oluşturulur. Her binding sınıfı, root view ve tüm viewlerin ID’sini içerir.

Örneğin, result_profile.xml adında bir layout dosyası olduğunu varsayalım.

<LinearLayout ... >
    <TextView android:id="@+id/name" />
    <ImageView android:cropToPadding="true" />
    <Button android:id="@+id/button"
        android:background="@drawable/rounded_button" />
</LinearLayout>

Oluşturulan binding sınıfına ResultProfileBinding adı verilir. Bu sınıfın iki view elemanı vardır: name adlı bir TextView ve button adlı bir Button. Layout içindeki ImageView‘in idsi yoktur. Bu yüzden binding sınıfı içerisinde örneği bulunmamaktadır.

Her binding sınıfı getRoot() metodunu içerir. getRoot() metodu, root viewin örneğini sağlar.

Activity İçerisinde Kullanımı

Bir activityde kullanmak üzere binding sınıfının bir örneğini ayarlamak için onCreate() methodunda aşağıdaki adımları gerçekleştirin:

  1. Oluşturulan binding sınıfında bulunan statik inflate() methodunu çağırın. Bu, activitynin kullanması için binding sınıfının bir örneğini oluşturur.
  2. getRoot() metodunu çağırarak root view örneği alın.
  3. Root viewi, ekranda etkin görünüm yapmak için setContentView() öğesine iletin.
private lateinit var binding: ResultProfileBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ResultProfileBinding.inflate(layoutInflater)
    val view = binding.root
    setContentView(view)
}

Artık viewlerden herhangi birini kullanmak için binding sınıfının örneğini kullanabilirsiniz:

binding.name.text = viewModel.name
binding.button.setOnClickListener { viewModel.userClicked() }

Fragment İçerisinde Kullanımı

Bir fragmentta kullanmak üzere binding sınıfının bir örneğini ayarlamak için onCreateView() methodunda aşağıdaki adımları gerçekleştirin:

  1. Oluşturulan binding sınıfında bulunan statik inflate() methodunu çağırın. Bu, fragmentın kullanması için binding sınıfının bir örneğini oluşturur.
  2. getRoot() metodunu çağırarak root view örneği alın.
  3. onCreateView() metodundan root view döndürün.
private var _binding: ResultProfileBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    _binding = ResultProfileBinding.inflate(inflater, container, false)
    val view = binding.root
    return view
}

override fun onDestroyView() {
    super.onDestroyView()
    _binding = null
}

Artık viewlerden herhangi birini kullanmak için binding sınıfının örneğini kullanabilirsiniz:

binding.name.text = viewModel.name
binding.button.setOnClickListener { viewModel.userClicked() }

NOT

Fragmentlar viewlerinden daha uzun yaşar. Bu yüzden onDestroyView() metodunda binding sınıfının örneğini temizleyin.


findViewById’den farklılıklar

View binding işleminin findViewById kullanımına göre önemli avantajları vardır:

  • Null safety: View binding viewlerin doğrudan referanslarını oluşturduğu için, geçersiz bir id nedeniyle NullPointerException hatası alma riski yoktur.
  • Type safety: Her binding sınıfındaki alanlar, XML dosyasında yer alan viewlerle eşleşen türe sahiptir. Bu da ClassCastException alma riski olmadığı anlamına gelir.

Bu farklılıklar, layout ve kodunuz arasındaki uyumsuzlukların, çalışma zamanında değil derleme zamanında başarısız olmasına neden olacağı anlamına gelir. Bu özelliği sayesinde uygulamanın hata fırlatıp kapanmasını engeller.

Data Binding ile Karşılaştırma

View Binding ve Data Binding, viewlere doğrudan başvurmak için kullanabileceğiniz binding sınıfları oluşturur. Bununla birlikte, view bindingin daha basit kullanım durumlarını ele alması amaçlanmıştır ve data bindinge göre aşağıdaki faydaları sağlar:

  • Daha hızlı derleme: View binding, anotasyon işleme gerektirmez, bu nedenle derleme süreleri daha hızlıdır.
  • Kullanım Kolaylığı: View binding, özel olarak etiketlenmiş XML layout dosyaları gerektirmez, bu nedenle uygulamalarınızda benimsemek daha hızlıdır.