看之前如果你发现做数据绑定的时候总是出错,你检查了一遍又一遍.都没有找出问题,
那肯定是 xml 文件格式错误了.为了节约时间,最好你重建 xml 文件.
首先简单介绍:
DataBinding 是 google 的数据绑定 MVVM模式
降低布局和逻辑的耦合性,
减少Activity 的代码量,
至于是不是能减少错误我就不敢苟同了.
下面针对这个数据绑定工具,介绍几个简单的步骤,让大家就不会
在第一次使用 数据绑定的时候掉到坑中.无法自拔
- . 首先在[类名]的 Activity 文件中 引入. DataBindingUtil包名
import android.databinding.DataBindingUtil;
就此: 此文件使用自动绑定工具 DataBindingUtil 就有根据了.
注意是 Databinding 不是 Databind 少了ing 就错误了.
现状来说第一个坑 必须开启数据功能,才能自动生成文件
- 在build.gradle 模块定义文件中定义
//要定义在 android 标签中
android {
//省略...
dataBinding {
enabled = true
}
// 省略...
}
有了.这个个坑, 当你使用
DataBindingUtil.setContentView(this,R.layout.activity_main);
这条语句的时候才会,自动发生代码的生成.到 generatedJava 目录中
当然在这之前 你必须 将布局文件先设置好
- 修改布局文件 例如文件名 是 activity_mian.xml
- 那么生成的数据绑定文件就是 ActivityMainBinding.java
数据绑定文件名是根据 Activity_main的文件名确定的
例如你 以 event_act.xml 那么 文件名就是 [eventact]binding
[] 中就是你的 布局文件名,
所以才有
ActivityMainBinding activityMainBinding=
DataBindingUtil.setContentView(this,R.layout.activity_main);
或者
EventActBinding eventactBinding=
DataBindingUtil.setContentView(this,R.layout.event_act);
- 所有的数据必须定义在数据模块中.
- 数据必须有 Get 和 Set 函数,和构造函数(便于参数)形式构建对象
public class User {
private String name;
private String password;
//构造函数
public User(String name, String password) {
this.name = name;
this.password = password;
}
//必须有具有 get ,set 函数
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
否则会出现 找不到 ,数据名的 绑定数据错误
错误: 找不到符号 的大坑
有了数据对象,就可以在布局文件中设置数据名称.
- 打开 activity_mian.xml 文件,选中
<android.support.constraint.ConstraintLayout
ConstraintLayout
然后 ALT + 回车,快捷键会弹出菜单
Convert to data binding layout (下来菜单中选中)
多出来 layout 标签 包裹起来,并且多出.data 标签
<data >
.......[设置区间]
</data>
多出
★把数据模块(Model )与 视图(View)控件 进行绑定
- 设定 绑定 数据的出处,定义数据模块的含义名称
import 声明数据模块
variable 声明新建并且使用的变量名
两个标签,
<data>
<import type="com.jackmacc.www.databindingtest.User" />
<variable
name="user"
type="User" />
</data>
- 变量与 TextView 控件的设定
随后 控件的 id 已经不重要了可以不设置
使用数据的时候 以 @ [运算符]{[模块名].[变量名]
<TextView
android:id="@+id/username"
···
android:text="@{user.name}" />
<TextView
android:id="@+id/userpws"
...
android:text="@{user.password}" />
- 使用 自动绑定,的对象必须在 Activity 类中,首先被声明否则没法使用.
private User user;
//声明后.
onCreate (){
ActivityMainBinding activityMainBinding=
DataBindingUtil.setContentView(this,R.layout.activity_main);
user=new User("mintor","12345");
activityMainBinding.setUser(user); //设置到数据绑定中.
//这样主界面就可以显示和使用这两个数据.
}
setContentView 不再有实际作用.
// setContentView(R.layout.activity_main);
谈谈数据绑定的方式
<import type="[类对象的地址/对象名]" />
<variable
name="[使用的变量名]"
type="[对象名]" />
- 在xml 中引用的 使用的变量名 必须具有在其构成类中句柄 , get() set() 和对象的必须具有 构造函数,
- 对象必须在 Activity 中 new [对象结构函数](参数1,参数…)
- 不能直接使用一些符号 < 和 >
- 在xml 使用的 “使用变量名” ,在 Activity 中,[绑定对象]binding,都具有 set[使用变量名],或者get[使用变量名],自动的构成函数.
<variable
name="dfefeex"
type="int"/>
<variable
name="key"
type="String"/>
- 一般的简单对象(数据类型) 也可以使用.
- 使用数据,或者对象的函数首先必须 进行 对象设定:
[绑定对象]binding.set[对象名](new 对象构造函数());
一个坑就是必须 使用 set[xml对象的定义名]
mEventBindBinding.setUserInfo(user);
mEventBindBinding.setUserhander(new UserHander()); //没有对象不响应
}
public class UserHander {
//android:onClick
public void onUserNameClick(User user) {
Toast.makeText(EventBind.this, "用户名:" + user.getName(),
Toast.LENGTH_SHORT).show();
}
// android:afterTextChanged
public void afterTextChanged(Editable s) {
user.setName(s.toString());
mEventBindBinding.setUserInfo(user);
}
public void afterUserPasswordChanged(Editable s) {
user.setPassword(s.toString());
mEventBindBinding.setUserInfo(user);
}
}
设定 后, 都可以在 Xml 中使用,否则不生效
<data>
<import type="com.jackmacc.www.goodsdatabind.Goods" />
<import type="com.jackmacc.www.goodsdatabind.MainActivity.GoodsHandler" />
<variable
name="goods"
type="Goods" />
<variable
name="goodsHandler"
type="GoodsHandler" />
</data>
<TextView
android:id="@+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{()->userhander.onUserNameClick(UserInfo)}"
android:text="@{UserInfo.Name,default=defaultValue}" />
<TextView
android:id="@+id/textView3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{UserInfo.Password,default=defaultValue}" />
<EditText
android:id="@+id/editText2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:afterTextChanged="@{userhander.afterTextChanged}"
android:hint="用户名" />
<EditText
android:id="@+id/editText3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:afterTextChanged="@{userhander.afterUserPasswordChanged}"
android:hint="密码" />
- Xml 文件中仍然可以传递参数
<Button
android:id="@+id/button3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{()->goodsHandler.openAtivity(3)}"
android:text="双向数据绑定(简单)"
android:textAllCaps="false" />
<Button
android:id="@+id/button4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{()->goodsHandler.openAtivity(4)}"
android:text="事件绑定"
android:textAllCaps="false" />
<Button
android:id="@+id/button5"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{()->goodsHandler.openAtivity(5)}"
android:text="ObservableGoods 测试 list map"
android:textAllCaps="false" />
在 Activity 中使用
public void onUserNameClick(Goods goods) {
Toast.makeText(MainActivity.this, "用户名:" + goods.getName(),
Toast.LENGTH_SHORT).show();
}
public void openAtivity(int num){
Intent intent=new Intent();
switch (num){
case 3:
intent.setClass(MainActivity.this,Edit_to_goods.class);
startActivity(intent);
break;
case 4:
intent.setClass(MainActivity.this,EventBind.class);
startActivity(intent);
break;
case 5:
intent.setClass(MainActivity.this,ObservableGoods_activity.class);
startActivity(intent);
break;
}