สวัสดีครับครั้งนี้จะมาพูดถึง databind ที่จะเป็นการที่เราจะผูก view กับ variable เข้าด้วยกัน ของ android นะครับ ก่อนอื่น เราสร้างโปรเจคขึ้นมาก่อนเลย

จากนั้นให้ทำการเปิด build.gradle ขึ้นมาแล้ว enable databinding ตามโค๊ดด้านล่างนี้เลยครับ

android {
...
    buildFeatures {
       dataBinding true
    }
}
build.gradle

ต่อไปเราจะทำการ  ใส่ code ตามด้านล่างเพื่อทำการ bind layout ครับ

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </LinearLayout>
</layout>
activity_main.xml

พอใส่แล้ว เปิดไฟล์ MainActivity ขึ้นมา ในช่อง onCreate() ให้เราเพิ่ม

  val binding: ActivityMainBinding =
            DataBindingUtil.setContentView(this, R.layout.activity_main)
MainActivity.kt
ActivityMainBinding จะถูกสร้างขึ้นมา อัตโนมัติ เมื่อเราทำการสร้าง <layout /> ครับ

เพียงเท่านี้ เราก็ได้ ทำการ bind เรียบร้อยแล้ว แต่บทความนี้เราจะทำการ binding  ให้มันเป็น two-ways binding โดยใช้ ViewModel นะครับ ให้เราสร้าง MainViewModel ขึ้นมาครับ

class MainViewModel : ViewModel()
MainViewModel.kt

จากนั้นให้เราเพิ่ม <variable /> เข้าไปใน <data /> ที่ ไฟล์ xml ตามนี้ครับ

  <data>
        <variable
            name="viewmodel"
            type="com.molysulfur.example.databinding.MainViewModel" />
  </data>
activity_main.xml

จากวิธีนี้ คือเราจะทำการ bind ViewModel เข้ากับ ตัวไฟล์ View  นั่นเองครับ

ต่อไปเรามาทำ logic ง่ายๆ สำหรับทำ Two-way Binding  

โดยจะให้มี text และ ปุ่มอยู่ตรงกลาง พอกดปุ่ม ให้  +1 โชว์ผลลัพท์ที่ text ครับ

จัด Layout กันก่อน code จะประมาณนี้

<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/main_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/main_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Click" />
    </LinearLayout>

ใน ViewModel ใส่ Logic นี้ไปครับ

class MainViewModel : ViewModel() {

    private val _numbers: MutableLiveData<Int> = MutableLiveData(0)

    var number : Int = 0
    val numbers: LiveData<Int> = _numbers

    fun onClick() {
        _numbers.value = (_numbers.value ?: 0) + 1
    }

}
MainViewModel.kt

เรียบร้อยครับ เราทำการ เตรียม variable และ/หรือ function ไว้ใน viewmodel เพื่อจะทำการ binding แล้วครับ

วิธีการ Binding

ถ้าเป็นการ Binding variable จะ ใช้เครื่องหมาย @{_} ส่วนข้างใน {} จะเป็นชื่อตัวแปร ที่อยู่ใน ViewModel

 android:text="@{variable}"

ส่วนถ้าเป็น function จะใส่ () -> functionName

@{() -> viewmodel.onClick()}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="viewmodel"
            type="com.molysulfur.example.databinding.MainViewModel" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/main_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{viewmodel.numbers.toString()}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/main_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{() -> viewmodel.onClick()}"
            android:text="Click" />
    </LinearLayout>
</layout>
full_code.xml

ลอง รันดูผลลัพธ์ครับ

แถมๆ

BindingAdapter เมื่อเราอยากทำเงื่อนไขบางอย่างให้กับ view binding adapater เป็น1ในตัวช่วย ถ้าสมมุติ ว่าเราอยากให้ text หายไป ตอน number = 10 จะทำยังไงนะ

สร้าง BindingAdapters.kt ขึ้นมา

object BindingAdapters {

    @BindingAdapter("app:hideIsTen")
    @JvmStatic
    fun hideIsTen(view: View, number: Int) {
        view.visibility = if (number == 10) View.GONE else View.VISIBLE
    }
    
}

BindingAdapters.kt

เป็นการบอกว่า ถ้าเราเติม app:hideIsTen ไปยัง view ใน xml มันจะเข้ามา เช็คในเงื่อนไขนี้เมื่อ number == 10 จะให้ View หายไป ครับผม

เป็นยังไงครับเขียนเข้าใจหรือไม่เข้าใจยังไง ต้องขออภัยด้วยนะครับ หรือสามารถ มาแชร์ความคิดเห็นในเพจเฟสบุ๊คผมได้นะครับ https://www.facebook.com/molysulfur ขอบคุณครับ


Data Binding in Android | Google Codelabs
The Data Binding Library allows you to bind UI components in your layouts to data sources in your app using a declarative format rather than programmatically. You’ll learn to set it all up, use layout expressions, work with observable objects, and create custom Binding Adapters to reduce boilerplate…
Data Binding Library | Android Developers
googlecodelabs/android-databinding
Contribute to googlecodelabs/android-databinding development by creating an account on GitHub.
molysulfur/data-binding
Contribute to molysulfur/data-binding development by creating an account on GitHub.