数据绑定¶
前面讲述了如何开始使用dataBinding。 本文讲述数据改变UI,动态更新的相关做法。
使用Observable¶
DataBinding提供了Observable
接口用于监听实体类对象属性的变化,Observable
接口有具有添加、删除监听的功能。为了简化开发,DataBinding已经为我们实现了一个基本的监听类BaseObservable
,实体类只要继承BaseObservable
,然后在get方法上加入@Bindable
注解,set方法中调用notifyPropertyChanged
通知UI更新就可以了。
这个方式相对来说较为麻烦。
继承BaseObservable
类¶
假设我们有一个类SysInfo
,代表着我们业务上的数据。
public class SysInfo {
private String info1 = Build.MANUFACTURER;
private String timeStr = "";
private long time;
// getter setter
}
让它继承BaseObservable
类,并给get方法添加@Bindable
注解。
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);
}
}
在get方法上加入@Bindable
注解后,编译一下工程,DataBinding就会在BR
文件中生成相应的字段。
BR
是编译期间生成的类,类似于R文件。
定义一个工具类DataUtils
,提供静态方法。
public class DataUtils {
private static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
public static String formatTime(long time) {
return format.format(time);
}
}
layout布局¶
在data标签下可以使用多个import标签,把需要使用的类导入进来。
引入工具类DataUtils
,声明使用SysInfo对象。
android:text
中使用的是@{}
表达方式。
<?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代码¶
在activity中,把SysInfo对象交给binding。 开启一个定时器去更新数据。
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();
}
}
运行后可以发现,数据是动态变化的。