一:使用DataBinding的第一步,只需要在app/build.gradle开启它
1android {
2 compileSdkVersion 28
3 defaultConfig {
4 applicationId "azhon.com.viewbinding"
5 //....
6 }
7 //开启dataBinding
8 dataBinding {
9 enabled = true
10 }
11}
二:将布局文件根元素修改为
1<?xml version="1.0" encoding="utf-8"?>
2<layout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 xmlns:tools="http://schemas.android.com/tools">
5
6 <data>
7
8 <import />
9
10 <variable />
11 </data>
12
13 <!-- layout 下只能有一个子节点 -->
14
15 <LinearLayout
16 android:layout_width="match_parent"
17 android:layout_height="match_parent">
18 <!-- 布局内容 -->
19
20 </LinearLayout>
21</layout>
在布局文件中我们可以通过快捷修复来将布局文件自动修改为符合databinding的布局
在这里插入图片描述
需要注意的是:layout 下只能有一个子节点
三:下面通过一些实例来介绍具体的使用
①为TextView绑定一个UserName
首先需要在xml
中指定variable
数据,然后在TextView进行绑定,如下:
1<?xml version="1.0" encoding="utf-8"?>
2<layout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 xmlns:tools="http://schemas.android.com/tools">
5
6 <data>
7 <!-- 指定数据 -->
8 <variable
9 name="userName"
10 type="String" />
11 </data>
12
13 <LinearLayout
14 android:layout_width="match_parent"
15 android:layout_height="match_parent">
16
17 <TextView
18 android:layout_width="match_parent"
19 android:layout_height="40dp"
20 android:gravity="center"
21 android:text="@{userName,default=我是默认的值}"
22 android:textColor="#333333" />
23 </LinearLayout>
24</layout>
在Activity中对这个布局加载,然后在设置userName
的值
1public class FirstMainActivity extends AppCompatActivity {
2 @Override
3 protected void onCreate(@Nullable Bundle savedInstanceState) {
4 super.onCreate(savedInstanceState);
5 FirstMainBinding dataBinding = DataBindingUtil.setContentView(this, R.layout.first_main);
6 //设置数据
7 dataBinding.setUserName("Hello 阿钟");
8 }
9}
1、Activity加载布局需要使用DataBindingUtil.setContentView()
,然后返回当前布局的*Binding对象,此类的命名规则为布局文件名称的驼峰命名
加上Binding:如activity_main
则为ActivityMainBinding
2、在布局中都是通过@{}
来进行引用变量、数据等
3、如果需要对字符串进行拼接的话就需要这样子写'@{"拼接字符串"+userName}'
②当然在布局中也是可以直接使用List、Map等
1<?xml version="1.0" encoding="utf-8"?>
2<layout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 xmlns:tools="http://schemas.android.com/tools">
5
6 <data>
7 <!--引入数据类型-->
8 <import type="java.util.List" />
9 <import type="java.util.Map" />
10
11 <!--与元素类型 "variable" 相关联的 "type" 属性值不能包含 '<' 字符。
12 这里 < 需要被转义为 <-->
13 <variable
14 name="list"
15 type="List<String>" />
16 <variable
17 name="map"
18 type="Map<String,String>" />
19 </data>
20
21 <LinearLayout
22 android:layout_width="match_parent"
23 android:layout_height="match_parent">
24
25 <!--取list集合中的第一个元素-->
26 <TextView
27 android:layout_width="match_parent"
28 android:layout_height="wrap_content"
29 android:text="@{list[0]}"/>
30 <!--取map集合中key = "key"元素-->
31 <TextView
32 android:layout_width="match_parent"
33 android:layout_height="wrap_content"
34 android:text='@{map.get("key")}' />
35 </LinearLayout>
36</layout>
然后通过当前布局文件的Binding对`List`、`Map`进行赋值,如下:
1public class FirstMainActivity extends AppCompatActivity {
2 @Override
3 protected void onCreate(@Nullable Bundle savedInstanceState) {
4 super.onCreate(savedInstanceState);
5 FirstMainBinding dataBinding = DataBindingUtil.setContentView(this, R.layout.first_main);
6 //设置数据
7 dataBinding.setList(Arrays.asList("Larry", "Moe", "Curly"));
8 HashMap<String, String> map = new HashMap<>();
9 map.put("key", "我是map的值");
10 dataBinding.setMap(map);
11 }
12}
③对View进行`onClick`事件绑定
1<?xml version="1.0" encoding="utf-8"?>
2<layout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 xmlns:tools="http://schemas.android.com/tools">
5
6 <data>
7 <variable
8 name="model"
9 type="com.azhon.viewbinding.FirstMainActivity" />
10 </data>
11
12 <LinearLayout
13 android:layout_width="match_parent"
14 android:layout_height="match_parent">
15 <!--第一种写法-->
16 <TextView
17 android:layout_width="match_parent"
18 android:layout_height="wrap_content"
19 android:onClick="@{model::click}"/>
20 <!--第二种写法-->
21 <TextView
22 android:layout_width="match_parent"
23 android:layout_height="wrap_content"
24 android:onClick="@{model.click}"/>
25 <!--第三种写法-->
26 <TextView
27 android:layout_width="match_parent"
28 android:layout_height="wrap_content"
29 android:onClick="@{()-> model.click2()}"/>
30 <!--第四种写法 调用有参数的函数-->
31 <!--theView 指代当前的TextView-->
32 <TextView
33 android:layout_width="match_parent"
34 android:layout_height="wrap_content"
35 android:onClick="@{(thisView)-> model.click3(thisView,12)}"/>
36 </LinearLayout>
37</layout>
相对应的Activity代码
1public class MainActivity extends AppCompatActivity {
2
3 @Override
4 protected void onCreate(@Nullable Bundle savedInstanceState) {
5 super.onCreate(savedInstanceState);
6 FirstMainBinding dataBinding = DataBindingUtil.setContentView(this, R.layout.first_main);
7 //对model进行赋值
8 mainBinding.setModel(this);
9 }
10
11 public void click(View view) {
12 Toast.makeText(this, "DataBinding点击事件", Toast.LENGTH_SHORT).show();
13 }
14 public void click2() {
15 Toast.makeText(this, "DataBinding点击事件(无参数)", Toast.LENGTH_SHORT).show();
16 }
17 public void click3(View view, int p) {
18 Toast.makeText(this, "DataBinding点击事件,参数:" + p, Toast.LENGTH_SHORT).show();
19 }
20}
④在布局中进行少量的运算,所支持的运算符如下:
!=
、%
、+
、-
、*
、/
、<
、>
、==
、<=
、>=
、<<
、>>
、>>>
或者使用三目运算符show ? View.VISIBLE : View.GONE
1<?xml version="1.0" encoding="utf-8"?>
2<layout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 xmlns:tools="http://schemas.android.com/tools">
5
6 <data>
7 <!--导入View类-->
8 <import type="android.view.View" />
9 </data>
10
11 <LinearLayout
12 android:layout_width="match_parent"
13 android:layout_height="match_parent">
14
15 <TextView
16 android:layout_width="match_parent"
17 android:layout_height="wrap_content"
18 android:text="@{String.valueOf(index + 1)}"
19 android:visibility="@{age > 13 ? View.GONE : View.VISIBLE}"
20 android:transitionName='@{"image_" + id}'/>
21 </LinearLayout>
22</layout>
四:dataBinding结合RecyclerView进行使用
①布局文件中添加RecyclerView
1<?xml version="1.0" encoding="utf-8"?>
2<layout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 xmlns:tools="http://schemas.android.com/tools">
5
6 <data>
7
8 </data>
9
10 <LinearLayout
11 android:layout_width="match_parent"
12 android:layout_height="match_parent"
13 android:orientation="vertical">
14
15 <android.support.v7.widget.RecyclerView
16 android:id="@+id/rv"
17 android:layout_width="match_parent"
18 android:layout_height="match_parent" />
19 </LinearLayout>
20</layout>
②创建一个实体类,用来做为RecyclerView的数据源User
1public class User {
2 private String userName;
3 private String userNum;
4
5 public String getUserName() {
6 return userName;
7 }
8
9 public void setUserName(String userName) {
10 this.userName = userName;
11 }
12
13 public String getUserNum() {
14 return userNum;
15 }
16
17 public void setUserNum(String userNum) {
18 this.userNum = userNum;
19 }
20}
③编写RecyclerView
的Item布局,引入User
这个实体类
1<?xml version="1.0" encoding="utf-8"?>
2<layout xmlns:android="http://schemas.android.com/apk/res/android">
3
4 <data>
5 <!-- Item的数据源为User -->
6 <variable
7 name="user"
8 type="com.azhon.viewbinding.User" />
9 </data>
10
11 <LinearLayout
12 android:layout_width="match_parent"
13 android:layout_height="wrap_content"
14 android:background="#eeeeee"
15 android:gravity="center_vertical"
16 android:orientation="vertical"
17 android:paddingHorizontal="16dp"
18 android:paddingVertical="8dp">
19
20 <TextView
21 android:id="@+id/tv_name"
22 android:layout_width="wrap_content"
23 android:layout_height="wrap_content"
24 android:text='@{"姓名:"+user.userName,default=阿钟}' />
25
26 <TextView
27 android:id="@+id/tv_num"
28 android:layout_width="wrap_content"
29 android:layout_height="wrap_content"
30 android:text='@{"序号:"+user.userNum,default=123456}' />
31 </LinearLayout>
32</layout>
④结合DataBinding
创建RecycleerView适配器
1public class TestAdapter extends RecyclerView.Adapter<TestAdapter.MyViewHolder> {
2
3 private List<User> users;
4 private Context context;
5
6 public TestAdapter(List<User> users, Context context) {
7 this.users = users;
8 this.context = context;
9 }
10
11 @NonNull
12 @Override
13 public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) {
14 LayoutInflater inflater = LayoutInflater.from(context);
15 ItemRvBinding binding = DataBindingUtil.inflate(inflater, R.layout.item_rv, parent, false);
16 return new MyViewHolder(binding.getRoot());
17 }
18
19 @Override
20 public void onBindViewHolder(@NonNull MyViewHolder holder, int i) {
21 ItemRvBinding binding = DataBindingUtil.getBinding(holder.itemView);
22 binding.setUser(users.get(i));
23 //迫使数据立即绑定
24 binding.executePendingBindings();
25 }
26
27 @Override
28 public int getItemCount() {
29 return users.size();
30 }
31
32 public class MyViewHolder extends RecyclerView.ViewHolder {
33 public MyViewHolder(View itemView) {
34 super(itemView);
35 }
36 }
37
38}
通过DataBindingUtil.inflate()
加载Item的布局,返回Item的*Binding对象
在onBindViewHolder
中设置Item的数据binding.setUser(users.get(i));
需要调用binding.executePendingBindings();
对数据进行立即绑定,防止数据错乱
⑤接下来就简单了,为Adapter设置数据即可
1FirstMainBinding dataBinding = DataBindingUtil.setContentView(this, R.layout.first_main);
2//通过dataBinding找到布局View
3RecyclerView recyclerView = dataBinding.rv;
4recyclerView.setLayoutManager(new LinearLayoutManager(this));
5List<User> users = new ArrayList<>();
6for (int i = 0; i < 30; i++) {
7 User user = new User();
8 user.setUserName("用户 " + i);
9 user.setUserNum(String.valueOf(Math.round(Math.random()) * 100000));
10 users.add(user);
11}
12TestAdapter adapter = new TestAdapter(users, this);
13recyclerView.setAdapter(adapter);