DataBinding在MVVM框架中的作用:为数据与xml文件实现了双向绑定。即数据的变化可以自动刷新界面,View在一些操作上也会自动的更新数据。减少了Activity的工作量。
1.使用DataBinding
在build.gradle中添加
dataBinding {
enabled = true
}
然后在xml文件的根标签上ALT + 回车键 然后选择Convert to data binding layout
最后变成:
根标签为layout,data标签里面就是我们要绑定的数据声明。
2.DataBinding的基本使用
我们先声明一个类:
public class Person {
public String name;
public String address;
public Person(String name, String address) {
this.name = name;
this.address = address;
}
}
在xml文件中也声明这个类
type指的是Person的全路径,name为Person的变量名。也可以使用import标签声明:
import标签中也可以使用 alias 属性 声明别名。
使用变量:
可以看到通过 @{变量名.属性}方式来引用。可以通过default来让xml显示默认值
在Activity中绑定数据:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
binding.setPerson(new Person("小王","南方"));
}
编译器会自动生成ActivityDataBinding类。如果你的xml文件名字为activity_main 就会生成ActivityMainBinding类。
3.DataBinding的事件绑定
方式一:
activity中
fun clickInfo(view: View){
Toast.makeText(this,"点击了",Toast.LENGTH_SHORT).show()
}
方式二:
在activity中:
绑定数据 binding.setEvent(this);
创建方法
public void getName(String name){
Toast.makeText(this, name, Toast.LENGTH_SHORT).show();
}
4.单向数据绑定
在绑定数据后,我们希望能做到数据变化后,UI也可以随着变化。DataBinding提供了三种方式:
BaseObservable,ObservableField,ObservableCollection
(1)BaseObservable
BaseObservable提供了notifyChange() 和 notifyPropertyChanged()两个方法。前者会刷新所有的值;后者则只更新有注解@Bindable的值。
public class Person extends BaseObservable {
private String name;
private String address;
private String info;
public Person(String name, String address, String info) {
this.name = name;
this.address = address;
this.info = info;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
@Bindable
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Bindable
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public void setNotifyChangeAll(){ //更新全部属性值
notifyChange();
}
public void setNotifyChangeSingle(){ //只更新address属性值
notifyPropertyChanged(BR.address);
}
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setPerson(person = new Person("小王", "南方", "舒服"));//绑定数据
binding.setEvent(this);//绑定事件
}
private Person person;
public void changeAll() { //更新属性值
person.setInfo("天气晴朗" + SystemClock.currentThreadTimeMillis());
person.setAddress("深圳" + SystemClock.currentThreadTimeMillis());
person.setName("小红" + SystemClock.currentThreadTimeMillis());
person.setNotifyChangeAll(); //调用全部更新方法
}
public void changeSingle() { // 更新属性值
person.setInfo("天气多云转阴" + SystemClock.currentThreadTimeMillis());
person.setAddress("广州" + SystemClock.currentThreadTimeMillis());
person.setName("小白" + SystemClock.currentThreadTimeMillis());
person.setNotifyChangeSingle(); //调用单个更新方法
}
}
(2)ObservableField
ObservableField 是对BaseObservable的封装,再也不需要手动的调用notifyChahange()和notifyPropertyChanged()了。
public class Person extends BaseObservable {
public ObservableField name = new ObservableField<>();
public ObservableField address = new ObservableField<>();
public ObservableField info = new ObservableField<>();
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
person = new Person();
person.name.set("小王");
person.address.set("南方");
person.info.set("阴雨绵绵");
binding.setPerson(person);
binding.setEvent(this);
}
private Person person;
public void changeAll() {
person.name.set("小芳" + SystemClock.currentThreadTimeMillis());
person.address.set("深圳" + SystemClock.currentThreadTimeMillis());
person.info.set("万里长空" + SystemClock.currentThreadTimeMillis());
}
public void changeSingle(){
}
}
(3)ObservableCollection
DataBinding提供了包装类用于替代原生的List和Map,分别是ObservableList 和 ObservableMap。
当其包含的数据发生变化时,绑定的视图也会随之进行刷新。
private ObservableArrayList listInfo; //创建ObservableArrayList
private ObservableArrayMap mapInfo; //创建ObservableArrayMap
listInfo = new ObservableArrayList<>();
listInfo.add("A");
listInfo.add("B");
mapInfo = new ObservableArrayMap<>();
mapInfo.put("a","苹果");
mapInfo.put("b","橘子");
binding.setKey("a");
binding.setLists(listInfo);//绑定数据
binding.setMaps(mapInfo); //绑定数据
在xml中引用:
需要注意的是:不要使用<>, 而是使用< 和 >代替它们。
数据变化时UI会自动更新
listInfo.set(0, "AA");
mapInfo.put("a","苹果苹果");
5.双向绑定
我们不只是希望能做到数据驱动UI的变化,同时我们也希望UI变化时,相应的数据有跟着变化。
注意:是 @={}
打印:tag: 阴雨绵绵bianchengwanliwuyunle
6.BindingAdapter
Databinding支持自定义属性。
public class Utils {
@BindingAdapter({"imageUrl"})
public static void setImageUrl(ImageView imageView, String url){
Log.e("tag",url);
}
}
xml中:
注意:当编译时提示找不到该属性时,可以Rebuild一下试试。
7.使用类方法
public class Utils {
@BindingAdapter({"imageUrl"})
public static void setImageUrl(ImageView imageView, String url){
Log.e("tag",url);
}
public static String toLower(String str){ //使用这个方法
return str.toLowerCase();
}
}
xml中:
8.空合并运算符 ??
当goodsInfo.info为空时,使用goodsInfo.details
9.属性控制
当goodsInfo.tag 不为空时,使用goodsInfo.name,否则使用 goodsInfo.details
10. include 和 ViewStub
layout_include.xml
activity_main.xml
绑定数据:
person = new Person();
person.name.set("小王");
person.address.set("南方");
person.info.set("阴雨绵绵");
binding.setPerson(person);
使用viewStub
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
View view = binding.viewstub.getViewStub().inflate();
person = new Person();
person.name.set("小王");
person.address.set("南方");
person.info.set("阴雨绵绵");
binding.setPerson(person);