一、DataBinding 的优劣势
1、优势
-
原生支持MVVM
在不改变原有代码构架上,让业务与UI分离
-
提高开发效率
XML 成为界面展示的唯一来源
减少重复代码 比如 findById 、setOnClick
-
功能强、安全性高
对于ID 与展示内容不符的UI 在编译期间提示
2、劣势
- 调试繁琐
二、基本使用
1、布局文件创建
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="model"
type="com.open.code.binding.MainActivity" />
</data>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
......
</LinearLayout>
</layout>
2、布局文件与页面结合
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setModel(this);
3、支持的数据类型
基本类型
-
集合
- 通用集合类型(arrays, lists, sparse lists, maps),通过['key' 获取]
-
资源
- 基本资源 drawable/string/color
- 特殊类型
Type Normal Reference Expression Reference String[] @array @stringArray int[] @array @intArray TypedArray @array @typedArray Animator @animator @animator StateListAnimator @animator @stateListAnimator color int @color @color ColorStateList @color @colorStateList -
表达式
- 数学计算 + - / * %
- 字符串连接 +
- 逻辑 && ||
- 二进制 & | ^
- 一元运算符 + - ! ~
- 位移 >> >>> <<
- 比较 == > < >= <=
- instanceof
- 组 ()
- 文字 - 字符,字符串,数字, null
- 类型转换
- 函数调用
- 字段存取
- 数组存取 []
- 三目运算符 ?:
4、数据更新
- Observable
//相对于BaseObservable 增加了一个 回调仓库同时也更接近通知的基础
public class UserObservableImp implements Observable {
private PropertyChangeRegistry mRegistry = new PropertyChangeRegistry();
//同样是在需要更新的字段位置加注解
@Bindable
public String name;
@Bindable
public String password;
public void setName(String name) {
this.name = name;
//在官网中使用的方法于此处不太一致 notifyPropertyChanged(int fieldId)
//但最终调用是一致的 其实就是做了一层基础的抽取 估计都懂
//在更新数据的地方添加 通知
mRegistry.notifyChange(this, BR.name);
}
public void setPassword(String password) {
this.password = password;
mRegistry.notifyChange(this, BR.password);
}
public String getName() {
return name;
}
public String getPassword() {
return password;
}
@Override
public void addOnPropertyChangedCallback(OnPropertyChangedCallback cb) {
mRegistry.add(cb);
}
@Override
public void removeOnPropertyChangedCallback(OnPropertyChangedCallback cb) {
mRegistry.remove(cb);
}
}
- BaseObservable
public class User extends BaseObservable {
//@Bindable 可以加到字段名上 也可以加载 get方法上 效果是一样
@Bindable
public String name;
@Bindable
public String password;
public String getName() {
return name;
}
//set方法上手动调用通知数据更新,此处不会自动生成
public void setName(String name) {
this.name = name;
notifyPropertyChanged(BR.name);
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
notifyPropertyChanged(BR.password);
}
}
- ObservableFiled
public final ObservableField<String> name = new ObservableField<>();
public final ObservableField<String> password = new ObservableField<>();
- ObservableCollection
5、ID
6、Include/ViewStub
<include
layout="@layout/view_image"
android:layout_width="match_parent"
android:layout_height="300dp"
bind:login="@{login}" />
三、双向绑定
android:text="@={login.code}"
android:text="@{login.code}"
四、BindingAdapter
@BindingAdapter({"android:url"})
public static void loadImage(ImageView view, String url) {
Util.log("url:"+url);
if (TextUtils.isEmpty(url)) return;
Glide.with(view.getContext()).load(url).into(view);
}
五、动画
//延迟动画
binder.addOnRebindCallback(new OnRebindCallback() {
@Override
public boolean onPreBind(ViewDataBinding binding) {
ViewGroup root = (ViewGroup) binding.getRoot();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
TransitionManager.beginDelayedTransition(root);
}
return true;
}
});
六、源码解析
1、运行流程
2157048-8afa93c6181d0275.png
2、View遍历
2157048-40b857f8f23ce7a4.png
七、注解
- 常用的
- @Bindable
- @BindingAdapter
- 默认实现的
- @BindingConversion
- @BindingMethod
- @BindingMethods
-反向绑定
- @InverseBindingAdapter
- @InverseBindingMethod
- @InverseBindingMethods
- @InverseMethod
@Untaggable
@BindingBuildInfo