Android DataBinding单向绑定
Android DataBinding单向绑定
一、Android DataBinding 基础使用
二、Android DataBinding单向绑定
三、Android DataBinding 双向数据绑定、事件绑定、使用类方法
DataBinding 是google
发布的一个数据绑定框架,用于降低布局和逻辑的耦合性,使代码逻辑更加清晰。大量减少 Activity 内的代码,数据能够单向或双向绑定到 layout 文件中,有助于防止内存泄漏,而且能自动进行空检测以避免空指针异常。
实现数据变化自动驱动 UI 刷新的方式有三种:BaseObservable
、ObservableField
、ObservableCollection
BaseObservable
一个简单的ViewModel
类被更新后,并不会让 UI 自动更新。而数据绑定后,我们自然会希望数据变更后 UI 会即时刷新,Observable
就是为此而生的概念。
BaseObservable 提供了 notifyChange() 和 notifyPropertyChanged() 两个方法。
- notifyChange()
它会刷新所有的值。
- notifyPropertyChanged()
它只会根据对应的BR
的flag
更新,该 BR
的生成通过注释 @Bindable
生成,可以通过 BR notify 特定属性关联的视图。
- 由于
kotlin
的属性默认是public
修饰,所以可以直接在属性上@Bindable
, 如何设置了修饰符且不为public
的话,则可使用@get BIndable
(表示在get()
方法上标记@Bindable
)
import androidx.databinding.BaseObservable
import androidx.databinding.Bindable
import com.github.ixiaow.sample.BR
class UserInfo : BaseObservable() {
// 对name进行@Bindable标志,然后会生成BR.name
@Bindable
var name: String = ""
set(value) {
field = value
// 当name,发生改变时只会刷新与name相关控件的值,不会刷新其他的值
notifyPropertyChanged(BR.name)
}
@get: Bindable
var password: String = ""
set(value) {
field = value
// 当password 发生改变时,也会刷新其他属性相关的控件的值
notifyChange()
}
}
布局文件:
<?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="userInfo" type="com.github.ixiaow.sample.model.UserInfo"/>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
app:layout_constraintVertical_chainStyle="spread"
android:id="@+id/mUserName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{userInfo.name}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{userInfo.password}"
app:layout_constraintTop_toBottomOf="@id/mUserName"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
-
OnPropertyChangedCallback
实现了 Observable 接口的类允许注册一个监听器
OnPropertyChangedCallback
,当可观察对象的属性更改时就会通知这个监听器。当中
propertyId
就用于标识特定的字段
user.addOnPropertyChangedCallback(object : Observable.OnPropertyChangedCallback(){
override fun onPropertyChanged(sender: Observable, propertyId: Int) {
}
})
ObservableField
继承于 Observable
类相对来说限制有点高,且也需要进行notify
操作,因此为了简单起见可以选择使用 ObservableField
。 可以理解为官方对 BaseObservable
中字段的注解和刷新等操作的封装,官方原生提供了对基本数据类型的封装,例如 ObservableBoolean、ObservableByte、ObservableChar、ObservableShort、ObservableInt、ObservableLong、ObservableFloat、ObservableDouble
以及 ObservableParcelable
,也可通过 ObservableField
泛型来申明其他类型。
data class ObservableUser(
var name: ObservableField<String>,
var password: ObservableField<String>
)
对 ObservableUser
属性值的改变都会立即触发 UI 刷新,概念上与Observable
区别不大,具体效果可看下面提供的源代码,这里不再赘述
ObservableCollection
dataBinding
也提供了包装类用于替代原生的 List
和 Map
,分别是 ObservableList
和 ObservableMap
,当其包含的数据发生变化时,绑定的视图也会随之进行刷新
<?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="androidx.databinding.ObservableList"/>
<import type="androidx.databinding.ObservableMap"/>
<import type="com.github.ixiaow.sample.model.User"/>
<variable name="index" type="int"/>
<variable name="key" type="String"/>
<variable name="list" type="ObservableList<User>"/>
<variable name="map" type="ObservableMap<String, User>"/>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
app:layout_constraintVertical_chainStyle="spread"
android:id="@+id/mUserName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{list[index].name}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{map[key].password}"
app:layout_constraintTop_toBottomOf="@id/mUserName"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val dataBinding: ActivityMainBinding =
DataBindingUtil.setContentView(this, R.layout.activity_main)
dataBinding.map = ObservableArrayMap<String, User>().apply {
"android" to User("android", "12367")
"java" to User("java", "12534")
"c" to User("c", "12344")
"c++" to User("c++", "14423")
"c#" to User("c#", "12334")
}
dataBinding.key = "c"
dataBinding.list = ObservableArrayList<User>().apply {
add(User("android", "123"))
add(User("java", "1234"))
add(User("c", "1235"))
add(User("c++", "123447"))
}
dataBinding.index = 3
}
}
本地址:https://blog.csdn.net/xiaowu_zhu/article/details/91876068
推荐阅读
-
android使用DataBinding来设置空状态
-
Android 代码一键实现银行卡绑定功能
-
Vuejs第一篇之入门教程详解(单向绑定、双向绑定、列表渲染、响应函数)
-
android studio 3.6.0 绑定视图新特性的方法
-
Vue.js单向绑定和双向绑定实例分析
-
Android开发中ListView绑定数据知识讲解
-
C#数据绑定(DataBinding)简单实现方法
-
vue.js数据绑定的方法(单向、双向和一次性绑定)
-
Android中的SQL查询语句LIKE绑定参数问题解决办法(sqlite数据库)
-
Android 用Databinding写recyclerview的adapter