动态更新和双向绑定
根据Model实体类的内容来动态更新UI,分别对应字段(ObservableField),类(Observable),集合类型(Observable 容器类)
1.使用Observable
首先我们需要定义Model实体类
import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;
import com.mvvm.BR;
public class Student extends BaseObservable {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Bindable
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
notifyPropertyChanged(BR.name);
}
@Bindable
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
notifyPropertyChanged(BR.age);
}
}
实体类注意三点
- 需要继承BaseObservable 类
- get方法添加@Bindable注解
- set方法添加notifyPropertyChanged(BR.age)告诉dataBind该数据的哪个属性变了
然后在Activity中使用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CustomBinding dataBind = DataBindingUtil.setContentView(this, R.layout.activity_main);
Student std = new Student("Tom",22);
dataBind.setStudent(std);
dataBind.tvName.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG,"name 的点击事件");
std.setName("小强");
}
});
}
这里只要一点击页面上的"Tom"就会自动变为"小强"。
2.使用ObservableField
我们也先自定义Model实体类
import androidx.databinding.ObservableField;
public class Student {
public ObservableField<String> name = new ObservableField<>();
public ObservableField<Integer> age = new ObservableField<Integer>();
public Student(String name, int age) {
this.name.set(name);
this.age.set(age);
}
public ObservableField<String> getName() {
return name;
}
public void setName(ObservableField<String> name) {
this.name = name;
}
public ObservableField<Integer> getAge() {
return age;
}
public void setAge(ObservableField<Integer> age) {
this.age = age;
}
}
这里需要关注两点
- 变量的申明用ObservableField<T>接收。
- 构造函数传进来的属性值要通过ObservableField的set方法设置进去。
在看看Activity中的代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CustomBinding dataBind = DataBindingUtil.setContentView(this, R.layout.activity_main);
Student std = new Student("Tom",22);
dataBind.setStudent(std);
dataBind.tvName.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG,"name 的点击事件");
std.name.set("小强");
}
});
}
通过这种方式,直接设置std.name.set(“小强”),也可以改界面显示。
3.使用Observable容器类
使用Observable容器类可以同时刷新多个对象。容器类有ObservableArrayList 和ObservableArrayMap。这里举例使用ObservableArrayList 。
对于Model类的使用几乎没有要求,按非data Binding的模式写也可以。
public class Teacher {
public String name;
public int age;
public Teacher(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
再看看布局文件的使用
<import type="com.mvvm.model.Teacher"/>
<import type="androidx.databinding.ObservableArrayList"/>
<variable
name="list"
type="ObservableArrayList<Teacher>" />
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{list[0].name}" />
<TextView
android:id="@+id/tv_name1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{list[1].name}" />
这里三个注意点
- 布局文件首先要导集合和元素的类的包
- 注意泛型的写法
- 注意集合的访问方式
4.双向绑定
双向绑定就是Model层数据发生了变化,UI层应该动态更新。UI层的显示发生了变化,Model数据层也应该随之改变。
双向绑定用法比较简单,只需要将android:text="@{teacher.name}“改成android:text=”@={teacher.name}"即可。
接下来我们用EditText试用一下
布局文件
<EditText
android:id="@+id/et"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="@={teacher.name}"/>
注意导包和变量的申明
Activity中的用法
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CustomBinding dataBind = DataBindingUtil.setContentView(this, R.layout.activity_main);
Teacher teacher = new Teacher("李白",18);
dataBind.setTeacher(teacher);
dataBind.et.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
String string = s.toString();
Log.d(TAG,"输入框数据是 :"+string);
Log.d(TAG,"teacher.name :"+teacher.getName());
}
});
}
}
看看打印结果:
2020-11-22 14:45:33.614 22908-22908/com.mvvm D/MainActivity: 输入框数据是 :李白
2020-11-22 14:45:33.614 22908-22908/com.mvvm D/MainActivity: teacher.name :李白
2020-11-22 14:45:38.372 22908-22908/com.mvvm D/MainActivity: 输入框数据是 :李
2020-11-22 14:45:38.372 22908-22908/com.mvvm D/MainActivity: teacher.name :李
2020-11-22 14:45:45.318 22908-22908/com.mvvm D/MainActivity: 输入框数据是 :
2020-11-22 14:45:45.318 22908-22908/com.mvvm D/MainActivity: teacher.name :
2020-11-22 14:45:47.833 22908-22908/com.mvvm D/MainActivity: 输入框数据是 :d
2020-11-22 14:45:47.833 22908-22908/com.mvvm D/MainActivity: teacher.name :d
2020-11-22 14:45:48.052 22908-22908/com.mvvm D/MainActivity: 输入框数据是 :du
2020-11-22 14:45:48.052 22908-22908/com.mvvm D/MainActivity: teacher.name :du