上一篇文章https://cloud.tencent.com/developer/article/1428728
,我们介绍了DataBinding以及DataBinding的简单的使用。可以看到,我们上一篇文章只是简单介绍了一下DataBinding,并没有详细介绍如何动态的加载数据。也就是说,这篇文章,我们将介绍,如何使用DataBinding让视图跟随这数据进行刷新变化。
观察者模式(Observer)完美的将观察者和被观察的对象分离开。举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。观察者模式有很多实现方式,从根本上说,该模式必须包含两个角色:观察者和被观察对象。
以上就是观察者模式的一个简单概念,而谷歌在这里开发的思想也是采用这种观察者模式的思想。
DataBinding的库,允许我们使用对象,字段,或者集合都可以进行观察。当其中的一个可观察者数据对象绑定到了视图当中,并且数据对象的属性发生更改变化的时候,视图将会自动更新。
ObservableField默认已经帮我们做了很多工作,比如实现了一系列的Observable接口的字段类型。
这其中包括
ObservableBoolean
ObservableByte
ObservableChar
ObservableShort
ObservableInt
ObservableLong
ObservableFloat
ObservableDouble
ObservableParcelable
在实际代码当中实际方式表现为。
通过代码实现的效果:
ObservableField.gif
我们的Model层为:
class Student {
val name = ObservableField<String>()
val age = ObservableInt()
}
代码当中实现为:
package com.yang.databindingdemo
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.yang.databindingdemo.databinding.ActivityMainBinding
import com.yang.databindingdemo.model.Student
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: ActivityMainBinding = DataBindingUtil.setContentView(
this, R.layout.activity_main
)
val studentInfo = Student()
studentInfo.name.set("我叫朝阳杨大爷")
studentInfo.age.set(20)
binding.studentInfo = studentInfo
binding.tvStudenname.setOnClickListener {
studentInfo.name.set("我还是叫叫朝阳杨大爷")
}
binding.tvAge.setOnClickListener {
studentInfo.age.set(18)
}
}
}
布局文件当中:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="com.yang.databindingdemo.model.Student"/>
<variable name="studentInfo"
type="Student"/>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv_studenname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{studentInfo.name,default = Yang}"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.377"/>
<TextView
android:id="@+id/tv_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(studentInfo.age),default = 18}"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.474"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
实现以上效果,我们还可以使用集合类型,这里为我们提供了三种数据结构类型。
ObservableArrayMap
ObservableArrayLis
ObjservableMap
这里我们以ObservableArrayMap为例:
我们在 Activity 当中代码为
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: ActivityMainBinding = DataBindingUtil.setContentView(
this, R.layout.activity_main
)
val map = ObservableArrayMap<String, Any>()
map["name"] = "我叫杨大爷"
map["age"] = 20
binding.studentInfo = map
}
}
然后布局文件当中为:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="androidx.databinding.ObservableArrayMap"/>
<variable name="studentInfo" type="ObservableArrayMap<String, Object>"/>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv_studenname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{studentInfo[`name`],default = Yang}"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.377"/>
<TextView
android:id="@+id/tv_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(studentInfo[`age`]),default = 18}"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.474"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
1.androidx的引用
注意,我们这里引用的 ObservableArrayMap 为 androidx 包下的,所以我们在布局文件当中引用的 ObservableArrayMap 为
androidx.databinding.ObservableArrayMap"
2.编译之后出现:与元素类型 "null" 相关联的 "type" 属性值不能包含 '<' 字符。的问题
在xml当中不能使用<应该用它的转义字符比如,<
所以,我们在代码当中需要修改为:
<variable name="studentInfo" type="ObservableArrayMap<String, Object>"/>
3.编译之后出现:/ data binding error msg:Identifiers must have user defined types from the XML file. name is missing it问题
多是因为,在引用的时候的问题 ObservableArrayMap 的key的问题,
这里,我们在引用的时候,注意
android:text="@{studentInfo[`name`],default = Yang}"
key上要有个英文的引号才可以。
4.当使用int给xml属性赋值时,如果该属性接受资源id,那么这个int会认为是资源的id。如果android:text=@{1}, 这样子text不会显示1,反而会报错,因为找不到id为1的资源
5.切记,达式里面不能有中文,否则会报错
6.在写表达式的时候,不能换行
通过这篇文章,我们真正的了解如何使用 DataBinding 并且了解了数据绑定,对于数据绑定的使用。
使用 DataBinding 确实代码会显得更加优雅一些,很多 UI 逻辑在 xml 文件当中就能实现了。
但是,我们一定要注意的是,在使用 DataBinding 的时候,应当注意要保持 xml 的简洁性, 不要再 xml 当中加入 过多的业务逻辑。
接下来我们将继续深入介绍 DataBinding 尽请期待!