书承上文,这次我们来探究一下DataBinding中控件事件的绑定和可观察对象的使用。
目录
一、自定义DataBinding生成类名以及import的使用
三、Observable Data Object(可观察数据对象)
一、自定义DataBinding生成类名以及import的使用
1、自定义DataBinding生成类名
在上篇文章中我们使用了一个名为ActivityMainBinding的类,这个类是DataBinding通过布局文件名称来生成的,规则是将布局文件的下划线去掉,每个单词首字母大写并且加上Binding后缀。但是,这样生成的名字有可能不符合实际开发的命名规则,因此,我们可以自定义生成名称。
首先,我们在布局文件的<data>标签里设置它的class属性,如下
<data class="MainBinding">
<variable
name="user"
type="com.silencer.db.entity.User" />
<variable
name="arr"
type="String[]" />
</data>
这样,系统给我们生成的类名就是MainBinding了,它位于**.databinding包下,如图
这里的MainBindingImpl继承MainBinding的类。同时,我们可以修改<data>的class值的形式来设置生成类在不同的包下等等。如<data class=".MainBinding">代表MainBinding位于根目录包下。
2、import的使用
在布局文件中,如果引入的变量包名过长,那么会很影响阅读。因此,我们可以使用import来导入某类。如下
<data class="MainBinding">
<import type="com.silencer.db.entity.User"/>
<variable
name="user"
type="User" />
<variable
name="arr"
type="String[]" />
</data>
可以发现,在使用import导入之后,我们对变量user的声明变得很简洁。同时,使用import导入某个类之后,我们可以很简洁的使用它的静态变量和方法,如下 可以看到我们在text的属性中引用了User类的静态变量Tag。
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/main_text"
android:text='@{User.TAG}'
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
如果引入多个类时,可能会发生冲突,这个时候就可以通过指定import的alias属性来给它设置一个别名,如下所示将User改名为People
<data class="MainBinding">
<import type="com.silencer.db.entity.User" alias="People"/>
<variable
name="user"
type="People" />
<variable
name="arr"
type="String[]" />
</data>
二、DataBinding中控件事件绑定
DataBinding的强大之处不仅在于可以动态绑定数据,而且还可以绑定控件的事件。我们以TextView的点击事件为例,使用三种方法来进行绑定。
①布局对应Activity的方法
我们首先在主函数中实现一下View.OnClickListener接口的onClick方法,如下
switch (v.getId()){
case R.id.main_text:
Toast.makeText(MainActivity.this,"点击了文本",Toast.LENGTH_SHORT).show();
break;
}
然后在布局文件中绑定这个事件,如下所示
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/main_text"
android:text='@{People.TAG}'
android:onClick="onClick"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
可以看到onclick属性中填入了onClick,这个值就是activity中匹配点击事件的接口。我们运行一下看看结果。
②自定义类成员方法
我们新建一个类,类名为TVEvent,如下
public class TVEvent {
public static void tvClick1(View v){
((TextView)v).setText("通过tvClick1点击事件");
}
public void tvClick2(View v){
((TextView)v).setText("通过tvClick2点击事件");
}
}
该类有一个公共的静态方法和一个公共的成员方法。我们在布局文件中引入这个类并声明变量。
......
<import type="com.silencer.db.callback.TVEvent"/>
<variable
name="tvEvent"
type="TVEvent" />
......
我们还需要在MainActivity给这个变量赋值,这里不贴代码,不懂得可以看第一篇文章。然后我们就可以使用成员方法来实现点击事件的绑定。
......
<TextView
......
android:text='@{People.TAG}'
android:onClick="@{(v)->tvEvent.tvClick2(v)}"
....../>
......
这里用的时lambda表达式来引用的。
③静态方法
这里和第二点很像,只不过可以直接使用类名.静态方法来绑定,如
......
<TextView
......
android:text='@{People.TAG}'
android:onClick="@{(v)->TVEvent.tvClick1(v)}"
....../>
......
注意,使用第二第三点方法时,要注意对象方法返回值与实践匹配的方法返回值一致,如onlick的返回值是void,那么tvClick1和tvClick2的返回值都应该为void
三、Observable Data Object(可观察数据对象)
注意,这里就是重点了。我们前面讲了这么久就是为了这一部分。DataBinding的提出就是为了使用可观察数据对象来实现动态更新。那么,什么是可观察数据对象呢?
从字面上来看,可观察对象就是你可以观察它的变化,相当于你在现实生活中订阅了某个公众号。当公众号更新时,他就会发送信息给你,告诉你它更新了内容。同理,可观察对象就是这个“公众号”。
可观测数据对象一般分为三类,分别为Observable Field,Obserable Collections和Obserable Object。我们一一讲解。
1、Observable Field
Observable Field(可观察字段),是一种拥有单一字段且自包可观察的对象,有如下几种:
- ObservableBoolean
- ObservableByte
- ObservableChar
- ObservableShort
- ObservableInt
- ObservableLong
- ObservableFloat
- ObservableDouble
- ObservableParcelable
这些对象都是包含着对应后缀的变量值,如ObservableBoolean是一个有boolean值的可观察对象。这些变量可以供其他对象订阅,在它们发生变化时,就会通知所有的观察者更新自己的信息。我们以ObservableInt来举例说明。
首先我们在布局文件中声明一个ObservableInt对象并将它绑定到TextView的text属性上面,如下
......
<variable
name="oInt"
type="androidx.databinding.ObservableInt" />
......
......
<TextView
......
android:id="@+id/main_text"
android:text='@{String.valueOf(oInt)}'
android:onClick="@{(v)->tvEvent.tvClick2(v)}"
...... />
......
然后我们传入要观察的ObservableInt对象,如下
......
ObservableInt oInt = new ObservableInt(0);
binding.setOInt(oInt);
new Thread(new Runnable() {
@Override
public void run() {
while (true){
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
oInt.set(oInt.get()+17);
}
}
}).start();
......
运行一下就可以看到文本在不停变动了,由于我不能截gif,所以没贴截图了。
2、Obserable Collections
Obserable Collections(可观察集合)是一组可以被观察的对象,它可以在集合发生变化时通知观察者,例如添加元素时。使用可观察集合的方法和可观察字段相近,话不多说直接看代码。
......
<variable
name="list"
type="androidx.databinding.ObservableList" />
......
......
<TextView
......
android:id="@+id/main_text"
android:text='@{list.size()>0?list[list.size()-1]:""}'
android:onClick="@{(v)->tvEvent.tvClick2(v)}"
...... />
......
......
ObservableList<String> oList = new ObservableArrayList<>();
binding.setList(oList);
new Thread(() -> {
while (true){
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
oList.add(System.currentTimeMillis()+"");
}
}).start();
......
运行即可看见效果。
3、Obserable Object
Obserable Object(可观察对象)是指实现Observable接口的对象,实际开发我们通常继承BaseObservable类来实现可观察对象。它可以通过在成员方法中调用notifyChange或notifyPropertyChanged来控制什么时候通知观察者发生了变化。使用方法也很简单,这里举个例子给大家说明一下。
首先,我们创建一个类,把他命名为ObservableBook,代码如下
public class ObservableBook extends BaseObservable {
@Bindable
private double price;
private String name;
private String author;
public ObservableBook() {
}
public ObservableBook(double price, String name, String author) {
this.price = price;
this.name = name;
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
notifyPropertyChanged(BR.price);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
notifyChange();
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
notifyChange();
}
}
这里price属性我使用notifyPropertyChanged方法来通知观察者,其他两个属性使用的时notifyChange来通知的,效果都一样。
DataBinding会生成一个BR类,他持有你声明的变量以及通过@Bindable注解标记的字段或get方法
使用的方法和其他可观察对象一样,这里就不举例了。本文到此结束,后面会给大家介绍生命周期绑定以及双向绑定的使用。
本BLOG上原创文章未经本人许可,不得用于商业用途。转载请注明出处并告知本人,否则保留追究法律责任的权利。