提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
DataBinding 使用教程 基础篇
前言
本篇文章用于记录自己根据官方文档学习DataBinding的记录和总结,若对你学习DataBinding 有助记得点赞呦。
一、DataBinding 是什么?
DataBinding 是 Android Jetpack 提供数据绑定库。借助该库,您可以使用声明性格式(而非程序化地)将布局中的界面组件绑定到应用中的数据源。
二、使用步骤
1.在项目中开启
在项目的 bulid.gradle 文件中添加一下代码开启
android {
...
dataBinding {
enabled = true
}
}
2.开始使用
1、先修改布局文件
数据绑定布局文件略有不同,以根标记 layout 开头,后跟 data 元素和 view 根元素。
修改该 xml 布局如下(Androd Studio 有快捷键 一键修改 鼠标点到跟布局 Alt +Enter 选中如图中所示 然后按enter 键)
2、布局中定义变量和导入引用类
1 、先定义变量 和导入引用类
2 、在根布局文件使用
以下代码展示了布局文件中的基本使用方法:(注释中有说明)
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
// 1、 定义变量 和导入引用类
// 所有使用的变量和引用类型要放在 <data> 标签下 data标签只能存在一个
// 若没有变量和引用类型 <data>标签下可以什么都不写
// 引用类型:使用 <import type =包名+.类名 /> 根据需求导入系统的定义类或自己定义的类
// 定义变量:使用 <variable name="变量名" type="包名+.类名, 基本类型可以直接使用"/>
// 注意:
// 1、支持基本数据类型和自定义类型 比如 String、int、 User(自定义类型)。
// 2、包名首字母要小写 如:com.example 不能 Com.example
// 3、类名首字母要大写 如:com.example.User 不能 com.example.user
<data>
// 导入引用类型
<import type="android.view.View" />
<import type="android.text.TextUtils" />
<import type="com.example.util.StringUtil" />
// 定义变量 定义后 Databinding 会自动生成 get set 方法
<variable
name="name"
type="String" />
<variable
name="price"
type="int" />
<variable
name="showPrice"
type="Boolean" />
// 使用自定义类型
<variable
name="user"
type="com.example.User"/>
</data>
// 2 、在根布局文件使用 语法: "@{ }" 或 ='@{ }' "@={ }" 双向绑定一般用于EditText
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
// 使用变量
// 拼接字符串 可以使用 '@{"用户名:" +name }'
// 还可以使用xml 定义的字符串 "@{@string/userName+':'+name}"
android:text="@{name}"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
// 通过定义的变量 控制 view 显示隐藏
// 可以使用表达三元表达式
android:visibility="@{showPrice?View.VISIBLE:View:GONE}"
// 引用的类型 使用基本类型不用导入包 可以直接使用
// 还可以直接使用String,"@{String.valueOf(price)}" 或 "@{price+1}"
android:text="@{StringUtil.intToString(price)}"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
//使用 自定类型 : 变量名.属性名(还可以是定义的 get方法名 如 public String getAllName(){}, "@{user.allName}" )
android:text="@{user.firstName}"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.lastName}"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
// 双向绑定
// EditText 中输入与的内容变化会直接更新 User中的 firstName 不需要在使用set方法设置内容
android:text="@={user.firstName}"/>
</LinearLayout>
</layout>
3、 在Activity 、Fragment、Dialog、PopupWindow、自定义View、includ标签 等使用
-
Databinging 自动生成的了的命名规则(大驼峰):layout文件名+Binding
如 @layout/activity_main Databinging会自动生成AcitvityMainBinding类 我们可以直接使用。 -
在自定义View中 一定要设置根布局View 的tag(view.setTag(“@laytout/layout文件名+_0”) _0 不能少如: 一定要设置, 一定要设置, 一定要设置,不要问我为啥知 道的 问就是一定要设置。
因为Databinging在自动生成文件时 会根据设 查找tag查找 在Activity 、Fragment等系统的类中已经帮我们自动设置了(setTag(@layout/activity_main_0))) 所以自定义view中一定要设置。
// 可封装到BaseAcitivty中不用每次都写一遍 extends BaseActivity<ActivityMainBinding >
public MainActivity extends AppCompatActivity{
// 使用BaseAcitivty 可以不用写
ActivityMainBinding binding;
// 使用BaseAcitivty 可以不用写 onCreate 方法
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
binding.setLifecycleOwner(this);
User user = new User("Test", "User");
binding.setUser(user);
binding.setName("张三");
binding.setPrice(100);
binding.setShowPrice(false)
}
// @Override
// protected int getLayoutId() {
// return R.layout.activity_main;
// }
// @Override
// protected void initView() {
// User user = new User("Test", "User");
// binding.setUser(user);
// binding.setName("张三");
// binding.setPrice(100);
// binding.setShowPrice(false)
// }
// 使用BaseAcitivty 可以不用写
@Override
protected void onDestroy() {
super.onDestroy();
if (binding != null) {
binding.unbind();
}
}
}
public class User {
public final String firstName;
public final String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
// 可以设置 也可以不设置
public voild setFirstName(String firstName ) {
this.firstName=firstName;
}
// 可以设置 也可以不设置
public voild setLastName(String lastName) {
this.lastName=lastName;
}
// 可以设置 也可以不设置
// 从数据绑定的角度来看,firstName getFirstName() 这两个类是等效的。
//用于 android:text 特性的表达式 @{user.} 访问前一个类中的 firstName 字段
//或 getFirstName() 方法。或者如果该方法存在也将解析firstName()。
public String getFirstName() {
return this.firstName;
}
// 可以设置 也可以不设置
public String getLastName() {
return this.lastName;
}
// 会自动生成 allName 在xml 中调用
public String getAllName (){
return fitrName+lastName;
}
}
// BaseActivity 的封装
public abstract class BaseActivity<DB extends ViewDataBinding> extends AppCompatActivity {
protected DB binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
beforeCreate(savedInstanceState);
super.onCreate(savedInstanceState);
if (getLayoutId() != 0) {
binding = DataBindingUtil.setContentView(this, getLayoutId());
binding.setLifecycleOwner(this);
}
initView();
initData();
}
protected void beforeCreate(Bundle savedInstanceState) {}
/**
* 设置布局资源文件Id
*
* @return 返回布局Id
**/
protected abstract int getLayoutId();
/**
* 初始化控件
**/
protected abstract void initView();
protected void initData() {}
@Override
protected void onDestroy() {
super.onDestroy();
ActivityManager.getInstance().removeActivity(this);
if (binding != null) {
binding.unbind();
}
}
}
表达式语言中使用以下运算符和关键字:
算术运算符 + - / * %
字符串连接运算符 +
逻辑运算符 && || (&需转义 &)
二元运算符 & | ^
一元运算符 + - ! ~
移位运算符 >> >>> <<
比较运算符 == > < >= <=(请注意,< 需要转义为 <)
instanceof
分组运算符 ()
字面量运算符 - 字符、字符串、数字、null
类型转换
方法调用
字段访问
数组访问 []
三元运算符 ?:
android:text="@{String.valueOf(index + 1)}"
android:visibility="@{age > 13 ? View.GONE : View.VISIBLE}"
android:transitionName='@{"image_" + id}'
缺少的运算
您可以在托管代码中使用的表达式语法中缺少以下运算:
this
super
new
显式泛型调用
Null 合并运算符
如果左边运算数不是 null,则 Null 合并运算符 (??) 选择左边运算数,如果左边运算数为 null,则选择右边运算数。
android:text=“@{user.displayName ?? user.lastName}”
这在功能上等效于:
android:text=“@{user.displayName != null ? user.displayName : user.lastName}”
避免出现 Null 指针异常
生成的数据绑定代码会自动检查有没有 null 值并避免出现 Null 指针异常。例如,在表达式 @{user.name} 中,如果 user 为 Null,则为 user.name 分配默认值 null。如果您引用 user.age,其中 age 的类型为 int,则数据绑定使用默认值 0。
视图引用
表达式可以通过以下语法按 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}"/>
注意:绑定类将 ID 转换为驼峰式大小写。
资源
表达式可以使用以下语法引用应用资源:
android:padding=“@{large? @dimen/largePadding : @dimen/smallPadding}”