数据绑定¶
更新日期 2022-9-1
- 2022-9-1 更新格式
- 2021-6-26 创建文档
前面讲述了如何开始使用dataBinding。本文讲述数据改变UI,动态更新的相关做法。
使用Observable¶
DataBinding
提供了Observable接口用于监听实体类对象属性的变化,Observable接口有具有添加、删除监听的功能。
为了简化开发,DataBinding
已经为我们实现了一个基本的监听类BaseObservable,实体类只要继承BaseObservable,然后在get方法上加入@Bindable
注解,set方法中调用notifyPropertyChanged
通知UI更新就可以了。
继承BaseObservable
类¶
假设我们有一个类SysInfo,代表着我们业务上的数据。这里用一些系统信息来演示。
SysInfo.java
让它继承BaseObservable类,并给get方法添加@Bindable
注解。
SysInfo继承BaseObservable类
public class SysInfo extends BaseObservable {
private String info1 = Build.MANUFACTURER;
private String timeStr = "";
private long time;
@Bindable
public String getInfo1() {
return info1;
}
public void setInfo1(String info1) {
this.info1 = info1;
notifyPropertyChanged(BR.info1);
}
@Bindable
public String getTimeStr() {
return timeStr;
}
public void setTimeStr(String timeStr) {
this.timeStr = timeStr;
notifyPropertyChanged(BR.timeStr);
}
@Bindable
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
notifyPropertyChanged(BR.time);
}
}
此时SysInfo类已经是“可被观测”的了。
set方法里我们都主动调用了notifyPropertyChanged
。
在get方法上加入@Bindable
注解后,编译一下工程,DataBinding
就会在BR
文件中生成相应的字段。
BR
是编译期间生成的类,类似于R文件。
定义一个工具类DataUtils
,提供静态方法。这个方法后面会在layout中用到。
DataUtils
layout布局¶
在data
标签下可以使用多个import
标签,把需要使用的类导入进来。
- 引入(
import
)工具类DataUtils
。 - 声明(
variable
)使用SysInfo对象。变量名定为info
。 - 给TextView设置显示的字符
android:text="@{info.timeStr}"
,其中使用的是@{}
表达方式。 - 使用工具类
DataUtils
的方法,使用的也是@{}
。
layout
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="com.rustfisher.tutorial2020.databinding.DataUtils" />
<variable
name="info"
type="com.rustfisher.tutorial2020.databinding.data.SysInfo" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{info.info1}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{info.timeStr}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{DataUtils.formatTime(info.time)}" />
</LinearLayout>
</layout>
除了直接使用对象的属性,还可以直接在xml中做一些操作,例如@{DataUtils.formatTime(info.time)}
。
如果在xml中使用了错误的类型,例如给TextView的text设置了long类型的属性,会在编译时报错。
使用了错误的类型
Found data binding errors.
data binding error msg:Cannot find the setter for attribute 'android:text' with arameter type long on android.widget.TextView.
在编译时报错能让开发者尽早发现错误。
Activity代码¶
之前我们在layout中设置了SysInfo变量,binding
会自动生成binding.setInfo()
方法。
在activity中,我们创建一个SysInfo对象,交给binding
。后面这个对象的数据发生改变时,界面会相应地改变。
为了演示数据变化,我们开启一个定时器去更新数据。
DataBindingAct1
public class DataBindingAct1 extends AbsActivity {
private ActDataBinding1Binding binding;
private SysInfo mSysInfo = new SysInfo();
private Timer mTimer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.act_data_binding_1);
binding.setInfo(mSysInfo);
mTimer = new Timer();
mTimer.schedule(new TimerTask() {
@Override
public void run() {
mSysInfo.setTimeStr("Time: " + System.currentTimeMillis());
mSysInfo.setTime(System.currentTimeMillis());
}
}, 0, 500);
}
@Override
protected void onDestroy() {
super.onDestroy();
mTimer.cancel();
}
}
运行后可以发现,数据是动态变化的。
本文介绍的是界面监听实体类对象属性变化的方法。
有兴趣的读者朋友可以尝试一下,binding.setInfo(mSysInfo);
后,重新创建mSysInfo
,看看界面还会不会动态变化。
在这个例子中,set方法里要主动调用notifyPropertyChanged
方法。有没有更简单的方式呢?
接下来我们看可观察数据对象ObservableField的用法。
本站说明
一起在知识的海洋里呛水吧。广告内容与本站无关。如果喜欢本站内容,欢迎投喂作者,谢谢支持服务器。如有疑问和建议,欢迎在下方评论~