Android数据绑定DataBinding(二)入门篇

前言

之前写了Android数据绑定DataBinding(一)入门篇,很简单的记录了如何使用DataBinding,其初衷是想要代码中的数据发生改变,不需要繁琐的setText等操作,在最后说到了只需要将POJO继承一个BaseObservable即可,其实这只是冰山一角啦!!!

本文若有出入,请指正——来自小渣渣的颤抖
本文接着上一篇的内容,记录一下数据对象事件处理

数据对象(Data Object)

其实继承BaseObservable的javBean叫做数据对象,官网介绍如下:

1
2
Any plain old Java object (POJO) may be used for data binding, but modifying a POJO will not cause the UI to update. The real power of data binding can be used by giving your data objects the ability to notify when data changes. There are three different data change notification mechanisms, Observable objects, observable fields, and observable collections.
When one of these observable data object is bound to the UI and a property of the data object changes, the UI will be updated automatically.

大意是:

1
2
任何普通的Java对象(PO​​JO)都可以用于数据绑定,但修改POJO不会导致UI更新。当数据改变的时候,您的数据对象能够发出通知,这才是数据绑定的威力。有三种不同的数据更改通知机制: Observable对象,observable字段, 和observable集合.
当这些observable数据对象之一被绑定到UI并且数据对象的属性改变时,UI将被自动更新。

Observable对象

这个就是我在Android数据绑定DataBinding(一)入门篇中最后介绍的那样,将我们的Bean继承 BaseObservable,这里再贴一下code;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class User extends BaseObservable{
private String userName;
private int age;
public User(String userName, int age) {
this.userName = userName;
this.age = age;
}
@Bindable
public String getUserName() {
return userName == null ? "" : userName;
}
public void setUserName(String userName) {
this.userName = userName;
notifyPropertyChanged(BR.userName);
}
@Bindable
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
notifyPropertyChanged(BR.age);
}
@Override
public String toString() {
return "User{" +
"userName='" + userName + '\'' +
", age=" + age +
'}';
}
}

可以看到在setter方法中调用了notifyPropertyChanged(BR.age);文档中这样介绍道:The Observable interface has a mechanism to add and remove listeners, but notifying is up to the developer.也就是说,这种机制允许开发者自己对被监听的字段进行添加和删除,我的理解就是(看你自己想绑定那些字段)。

ObservableFields

相比于上一种方式,使用ObservableFields则可以减少许多的工作量,因为我们可以许多提供的类型,文档介绍如下:ObservableField and its siblings ObservableBoolean, ObservableByte, ObservableChar, ObservableShort, ObservableInt, ObservableLong, ObservableFloat, ObservableDouble, and ObservableParcelable.
示例:

1
2
3
4
5
6
7
8
9
10
public class People {
public ObservableField<String> name = new ObservableField<>();
public ObservableInt age = new ObservableInt();
public ObservableList<String> list = new ObservableArrayList<>();
public People(String name, int age, ArrayList<String> list) {
this.name = new ObservableField<>(name);
this.age = new ObservableInt(age);
this.list = (ObservableArrayList)list;
}
}

这样就不需要我们自己在getter上设置@binding,在setter中设置notifyPropertyChanged(int)了。

Observable 集合

官方列举了这样两个例子,ObservableArrayMapObservableArrayList,其中对ObservableArrayMap的介绍是key是String这样的类型时,是非常有用的,示例如下:

1
2
3
4
ObservableArrayMap<String, Object> user = new ObservableArrayMap<>();
user.put("firstName", "Google");
user.put("lastName", "Inc.");
user.put("age", 17);

在layout中

1
2
3
4
5
6
7
8
9
10
11
12
13
<data>
<import type="android.databinding.ObservableMap"/>
<variable name="user" type="ObservableMap<String, Object>"/>
</data>

<TextView
android:text='@{user["lastName"]}'
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:text='@{String.valueOf(1 + (Integer)user["age"])}'
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

我的理解就是一些集合类型的封装使用。

事件处理(Event Handling)

之前对某个View设置某种监听事件是通过setXXXX,在数据绑定中是如何实现的呢,有两种方式

  • 方法引用(Method References)
  • 监听器绑定(Listener Bindings)
    方法引用(Method References)
    其实这种方法在之前也使用过,较多的是button的onClick事件,通常是直接在布局中写上相应Activity中的方法即可,其实这就是方法引用,学习官网的例子,我写的demo示例如下:
  • 布局文件中

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <variable
    name="presenter"
    type="com.jiajia.mypractisedemos.module.jetpack.JetpackActivity.Presenter"/>
    ......
    <Button
    android:text="click"
    android:textAllCaps="false"
    android:onClick="@{presenter.onClick}"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
  • Activity中

    1
    2
    3
    4
    5
    6
    public class Presenter {
    public void onClick(View view) {
    people.name.set("啊啊啊啊啊");
    Toast.makeText(JetpackActivity.this, "点击了Button",Toast.LENGTH_SHORT).show();
    }
    }

这里注意必须给定参数View view,即需要符合事件监听的写法。

监听器绑定(Listener Bindings)

这个说真的,没特别理解,简单整理一下,英文文档说:在方法引用中,方法的参数必须与事件监听器的参数匹配。在监听器绑定中,只有你的返回值必须与监听器的期望返回值相匹配(除非它预期为void),例如:

1
2
3
public class Presenter {
public void onSaveClick(Task task){}
}

然后,您可以将click事件绑定到您的类,如下所示:

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="task" type="com.android.example.Task" />
<variable name="presenter" type="com.android.example.Presenter" />
</data>
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent">
<Button android:layout_width="wrap_content" android:layout_height="wrap_content"
android:onClick="@{() -> presenter.onSaveClick(task)}" />
</LinearLayout>
</layout>

注意这里没有传入view参数,可能这就是与方法引用不同之处,当然也可以传啦,android:onClick="@{(view) -> presenter.onSaveClick(task)}",还有好几种,也不知道什么情况下用,也不懂,不写了,以后用到再说。我觉得就方法引用的方式用得比较多,比较太low了平时写的代码。

方法引用和监听器绑定的主要区别在于实际的监听器实现是在绑定数据时创建的,而不是在事件触发时创建的。如果您喜欢在事件发生时计算表达式,则应该使用监听器绑定。

最后

下午6点了,好饿,去食堂吃麻辣烫了!

此致,敬礼

~~客官随意,我只是学习怎么配置打赏而已~~