[Android] Two ways Binding
![[Android] Two ways Binding](/content/images/size/w960/2020/12/ship-white-ropes-tied-knot.jpg)
สวัสดีครับครั้งนี้จะมาพูดถึง databind ที่จะเป็นการที่เราจะผูก view กับ variable เข้าด้วยกัน ของ android นะครับ ก่อนอื่น เราสร้างโปรเจคขึ้นมาก่อนเลย
จากนั้นให้ทำการเปิด build.gradle ขึ้นมาแล้ว enable databinding ตามโค๊ดด้านล่างนี้เลยครับ
android {
...
buildFeatures {
dataBinding true
}
}
ต่อไปเราจะทำการ ใส่ 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>
พอใส่แล้ว เปิดไฟล์ MainActivity ขึ้นมา ในช่อง onCreate() ให้เราเพิ่ม
val binding: ActivityMainBinding =
DataBindingUtil.setContentView(this, R.layout.activity_main)
ActivityMainBinding จะถูกสร้างขึ้นมา อัตโนมัติ เมื่อเราทำการสร้าง <layout /> ครับ
เพียงเท่านี้ เราก็ได้ ทำการ bind เรียบร้อยแล้ว แต่บทความนี้เราจะทำการ binding ให้มันเป็น two-ways binding โดยใช้ ViewModel นะครับ ให้เราสร้าง MainViewModel ขึ้นมาครับ
class MainViewModel : ViewModel()
จากนั้นให้เราเพิ่ม <variable /> เข้าไปใน <data /> ที่ ไฟล์ xml ตามนี้ครับ
<data>
<variable
name="viewmodel"
type="com.molysulfur.example.databinding.MainViewModel" />
</data>
จากวิธีนี้ คือเราจะทำการ 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
}
}
เรียบร้อยครับ เราทำการ เตรียม 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>
ลอง รันดูผลลัพธ์ครับ
แถมๆ
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
}
}
เป็นการบอกว่า ถ้าเราเติม app:hideIsTen ไปยัง view ใน xml มันจะเข้ามา เช็คในเงื่อนไขนี้เมื่อ number == 10 จะให้ View หายไป ครับผม
เป็นยังไงครับเขียนเข้าใจหรือไม่เข้าใจยังไง ต้องขออภัยด้วยนะครับ หรือสามารถ มาแชร์ความคิดเห็นในเพจเฟสบุ๊คผมได้นะครับ https://www.facebook.com/molysulfur ขอบคุณครับ

