So we talked about the basics of DataBinding. BaseObservable DataBinding BaseObservable DataBinding BaseObservable BindingAdapter and BindingConversion DataBinding advanced section 4-way DataBinding
Three: Using observable data objects (one-way data binding)
There are three ways to implement data changes and automatically notify UI updates: BaseObservable, ObservableField, and ObservableCollection
3.1 BaseObservable
Implementing the Observable interface has mechanisms for adding and removing listeners, but you must decide when to send notifications. For development purposes, the data binding library provides a BaseObservable class that implements the listener registration mechanism. The data class that implements a BaseObservable notifies properties when they change. This is done by assigning the Bindable annotation to the getter and then calling the notifyPropertyChanged() method in the setter. Create an ObserableUser class that extends from BaseObservable, as shown in the following example
class ObserableUser :BaseObservable() {@get:Bindable
var name = ""
set(value) {
field = value
// Refresh the current property only
notifyPropertyChanged(BR.name)
}
var price = 0f
@get:Bindable
var age = 0
set(value) {
field = value
// Update all fields
notifyChange()
}
}
Copy the code
- @get:Bindable Generates the BR class with the Bindable annotation get method
- The notifyPropertyChanged() method notifies updating a field, above which is updating only Br.name, which is generated using the @bindable annotation
- NotifyChange () updates all fields
The code in the activity_main.xml file is as follows:
<? 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>
<import type="com.example.jetpackdatabindingtestapp.ui.helper.ClickHelper" />
<import type="com.example.jetpackdatabindingtestapp.ui.model.ObserableUser" />
<variable name="obserableUser" type="ObserableUser" />
<variable name="clickHelper" type="ClickHelper" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_obserable_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{obserableUser.name}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_obserable_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@ {String. The valueOf (obserableUser. Age) + ', '}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_obserable_name" />
<TextView
android:id="@+id/tv_obserable_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@ {String. The valueOf (obserableUser. Price) + 'yuan'}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_obserable_age" />
<Button
android:id="@+id/btn_change_user_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{()->clickHelper.onChangeName(obserableUser)}"
android:text="Change your name"
app:layout_constraintEnd_toStartOf="@+id/btn_change_user_age"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_obserable_price" />
<Button
android:id="@+id/btn_change_user_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{()->clickHelper.onChangeAge(obserableUser)}"
android:text="Change your age."
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/btn_change_user_name"
app:layout_constraintTop_toBottomOf="@+id/tv_obserable_price" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Copy the code
ClickHelper class
class ClickHelper() {fun onChangeName(userObserableUser: ObserableUser){
userObserableUser.name +=userObserableUser.age
userObserableUser.price++
}
fun onChangeAge(userObserableUser: ObserableUser){
userObserableUser.age++
userObserableUser.price++
}
}
Copy the code
MainActivity
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?). {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this,R.layout.activity_main)
val observableUser = ObserableUser()
observableUser.name = "ccm"
observableUser.age = 21
binding.obserableUser = observableUser
binding.clickHelper = ClickHelper()
}
}
Copy the code
The refresh of name does not refresh price at the same time as the refresh of age does. When the attribute value change, will be a OnPropertyChangedCallback callback, we could add OnPropertyChangedCallback monitor
obserableUser.addOnPropertyChangedCallback(object : Observable.OnPropertyChangedCallback() {
override fun onPropertyChanged(sender: Observable? , propertyId:Int) {
when(propertyId){
BR.name->{}
BR._all->{}
BR.age->{}
else- > {}}}})Copy the code
3.2 ObservableField
It is relatively complicated to use ObservableField inherited from Observable class and requires notify operation to refresh UI. If our property definition is simple, ObservableField can be used. ObservableField is an official encapsulation of field annotation and refresh operations in a BaseObservable. The ObservableField can be used directly to refresh UI by modifying property values.
- ObservableBoolean
- ObservableByte
- ObservableChar
- ObservableShort
- ObservableInt
- ObservableLong
- ObservableFloat
- ObservableDouble
- ObservableParcelable
ObservableField
, ObservableField
, ObservableField
Create a Teacher class with three properties firstName, teacherAge, and price
class Teacher{
val firstName = ObservableField<String>()
val teacherAge = ObservableInt()
val price = ObservableDouble()
}
Copy the code
One activity_field. XML layout, three text, three buttons. Three text displays firstName, teacherAge, price values, and three buttons change firstName, teacherAge, price values
<? 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>
<import type="com.example.jetpackdatabindingtestapp.ui.model.Teacher" />
<import type="com.example.jetpackdatabindingtestapp.ui.helper.ClickTeacherHelper"/>
<variable
name="teacher"
type="Teacher" />
<variable
name="clickTeacherHelper"
type="ClickTeacherHelper" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_teacher_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{teacher.firstName}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_teacher_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{string.valueof (teacher.teacherage)+ 'old teacher'}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_teacher_name" />
<TextView
android:id="@+id/tv_teacher_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@ {String. The valueOf (the teacher) price) + ` yuan `}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_teacher_age" />
<Button
android:id="@+id/btn_change_teacher_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Change your name"
android:onClick="@{()->clickTeacherHelper.onChangeName(teacher)}"
app:layout_constraintEnd_toStartOf="@+id/btn_change_teacher_age"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_teacher_price" />
<Button
android:id="@+id/btn_change_teacher_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Change your age."
android:onClick="@{()->clickTeacherHelper.onChangeAge(teacher)}"
app:layout_constraintEnd_toStartOf="@+id/btn_change_teacher_price"
app:layout_constraintStart_toEndOf="@+id/btn_change_teacher_name"
app:layout_constraintTop_toBottomOf="@+id/tv_teacher_price" />
<Button
android:id="@+id/btn_change_teacher_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Change the price"
android:onClick="@{()->clickTeacherHelper.onChangePrice(teacher)}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/btn_change_teacher_age"
app:layout_constraintTop_toBottomOf="@+id/tv_teacher_price" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Copy the code
ClickTeacherHelper, a class that handles events
class ClickTeacherHelper {
fun onChangeName(teacher: Teacher){
var name = teacher.firstName.get()? :""
teacher.firstName.set(name+name)
}
fun onChangeAge(teacher: Teacher){
var age = teacher.teacherAge.get()
teacher.teacherAge.set(++age)
}
fun onChangePrice(teacher: Teacher){
var price = teacher.price.get()
teacher.price.set(++price)
}
}
Copy the code
An Activity class
class FieldActivity :AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?). {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ActivityFieldBinding>(this,R.layout.activity_field)
val teacher = Teacher()
teacher.firstName.set("Oh, Chunming Chen.")
teacher.teacherAge.set(11)
teacher.price.set(10.0)
binding.teacher = teacher
binding.clickTeacherHelper = ClickTeacherHelper()
}
}
Copy the code
3.3 ObservableCollection
DataBinding also provides the collection List and Map, ObservableList and ObservableMap. The UI can be automatically updated when data changes, as shown in the following example: an Activity class
class FieldActivity :AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?). {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ActivityFieldBinding>(this,R.layout.activity_field)
val observableArrayList = ObservableArrayList<String>()
observableArrayList.add("Chinese")
binding.list = observableArrayList
binding.index = 0
val observableArrayMap = ObservableArrayMap<String,String>()
observableArrayMap.put("course"."Chinese")
binding.map = observableArrayMap
binding.key = "course"
binding.btnChangeList.setOnClickListener{
observableArrayList.clear()
observableArrayList.add("Mathematics")
observableArrayMap.clear()
observableArrayMap.put("course"."Mathematics")}}}Copy the code
A layout file
<? 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>
<import type="com.example.jetpackdatabindingtestapp.ui.model.Teacher" />
<import type="com.example.jetpackdatabindingtestapp.ui.helper.ClickTeacherHelper" />
<import type="androidx.databinding.ObservableArrayMap" />
<import type="androidx.databinding.ObservableArrayList" />
<variable
name="list"
type="ObservableArrayList< String>" />
<variable
name="map"
type="ObservableArrayMap< String,String>" />
<variable
name="index"
type="int" />
<variable
name="key"
type="String" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_list_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{list[index]}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_map_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{map[key]}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_list_name" />
<Button
android:id="@+id/btn_change_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Change the set"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_map_name" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Copy the code