DataBinding
这是我参与「第四届青训营 」笔记创作活动的第1天
在Android实现MVVM架构, 那么DataBinding是很好的选择
- findviewById只是他的一小部分内容,如果只是替换findviewById官方推荐用viewBinding
- ViewModel属于DataBinding自动生成的类
android {
...
dataBinding {
enabled = true
}
}
1:XML布局详解
基本的布局结构如下所示
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="viewmodel"
type="com.myapp.data.ViewModel" />
</data>
<ConstraintLayout... /> <!-- UI layout's root element -->
</layout>
-
布局根节点必须是 ,同时layout只能包含一个view标签
-
标签来指定类
-
<variable name="user"<!--类对象--> type="com.yxl.databing.UserBean" />type需要指定具体的数据类的包名
-
或者像导包一样
-
<import type="com.yxl.databing.UserBean" /> <variable name="user" type="UserBean" />
-
-
allas 可以在两个类名相同(不同的包下的相同类名)的时候 重命名来加以区分
-
<import type="com.yxl.databing.UserBean" alias="MyUserBean"/> <variable name="user" type="MyUserBean" />
-
-
include
- 在一个layout被include的时候,可能需要传递变量的值
-
<include layout="@layout/include_view" bind:userName="@{user}"/>
2:获取binding类的方式
activity中使用
- 方式一
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
2.方式二
ActivityMainBinding activityMainBinding1=ActivityMainBinding.inflate(getLayoutInflater());
此方法与viewBinding 获取的方法类似
在 Fragment、ListView 或 RecyclerView 适配器中使用数据绑定项
ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
// or
ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);
然后绑定数据
activityMainBinding.setUser(user);
3:属性使用
自己bean类的属性
android:text="@{user.lastName}"
除了使用自己定义的类的属性,还可以使用其他控件的数据
通过id(驼峰命名法转化)引用
<EditText
android:id="@+id/example_text"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
<TextView
android:id="@+id/example_output"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{exampleText.text}"/>
如图所示可以根据edittext实时改变textview
<运算符需要转义为 <
由于
<在在xml语言中的特殊性在运算时需要转义
android:text="@{user.age<5? @string/app_name : @string/kkk}"
-
使用字面字符串
-
资源文件用@ 来引用
-
null 合并运算符:
null 合并运算符(??)左边不为 null 或正确,则返回左边,否则返回右边
避免出现 Null 指针异常
生成的数据绑定代码会自动检查有没有 null 值并避免出现 Null 指针异常。例如,在表达式 @{user.name} 中,如果 user 为 Null,则为 user.name 分配默认值 null。如果您引用 user.age,其中 age 的类型为 int,则数据绑定使用默认值 0。
关于defalut
android:text="@{user.lastName,default=myName}"
default只是在开发时可以在preview界面有一个预览效果,在实际运行之后不会显示
4:可观察的数据类
在数据改变之后通知ui来更新
1:BaseObservable
package com.yxl.roomdatabase;
import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;
/**
* @author yinxiaolong
* @describe
* @data:
*/
public class MyBean extends BaseObservable {
String name;
String age;
@Bindable
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
notifyPropertyChanged(BR.name);
}
@Bindable//如果属性时public直接在属性前加注解就可以
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
notifyPropertyChanged(BR.age);//通知改变
}
}
2:observableField
ObservableBooleanObservableByteObservableCharObservableShortObservableIntObservableLongObservableFloatObservableDoubleObservableParcelable
Java 编程语言创建 public final 属性,或在 Kotlin 中创建只读属性,
private static class User {
public final ObservableField<String> firstName = new ObservableField<>();
public final ObservableField<String> lastName = new ObservableField<>();
public final ObservableInt age = new ObservableInt();
}
如需访问字段值,请使用 set() 和 get() 访问器方法
在activity中更新数据
MyObservableFildeBean myObservableFildeBean=new MyObservableFildeBean();
activityMainBinding.setMyObserableBean(myObservableFildeBean);
myObservableFildeBean.age.set(18);
myObservableFildeBean.firstName.set("firstName");
myObservableFildeBean.lastname.set("lastname");
-
observableArrayMap 容器类使用
xml中
<data> <import type="androidx.databinding.ObservableMap"/> <variable name="obserableMap" type="ObservableMap<String,Object>" /> </data> ..... android:text="@{String.valueOf(obserableMap.google)}"activity中
ObservableMap<String , Object> objectObservableMap=new ObservableArrayMap<>();
activityMainBinding.setObserableMap(objectObservableMap);
objectObservableMap.put("google",100);
objectObservableMap.put("vivo",78);
此外还有ObservableArrayList
5:双向绑定数据
前面是model改变后view自动动态跟新
也支持view改变使model改变
主要就是将原来的 @{....} 表达式改变为 @={...}
此时需要注意是否会出现无限循环的问题,在数据不变时就不进行更新
public class LoginViewModel extends BaseObservable {
// private Model data = ...
@Bindable
public Boolean getRememberMe() {
return data.rememberMe;
}
public void setRememberMe(Boolean value) {
// Avoids infinite loops.
if (data.rememberMe != value) {
data.rememberMe = value;
// React to the change.
saveData();
// Notify observers of a new value.
notifyPropertyChanged(BR.remember_me);
}
}
}