Android 数据绑定简单使用
Table of Contents
1 Android 数据绑定简单使用
这次我们要替代获取控件的方法,以前是使用 findViewById
一个一个拿到控件
现在我们需要直接在 layout
中注入数据对象,我们还要直接通过 id
访问到控件
1.1 数据绑定
1.1.1 启用数据绑定
在 build.gradle
中添加如下代码
android { dataBinding { enable = true } }
即可开启数据绑定
1.1.2 修改布局文件
先看 Vue 中的数据绑定是怎样操作的
<template> <div class="container"> <span> {{data}} </span> </div> </template> <script lang="ts" setup> const data = 'hello' </script>
在 XML 中
layout
类似template
- 使用
data
标签声明数据
假设有数据类型 User
public class User { public String name; public String password; public User(String name, String password) { this.name = name; this.password = password; } }
先在 activity_main
中声明数据
<data> <varibale name="userInfo" type="com.example.databinding.User"/> </data>
再在控件中注入数据
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="20dp" android:orientation="vertical"> <TextView android:id="@+id/tv_userName" android:text="@{userInfo.name}" /> <TextView android:text="@{userInfo.password}" /> </LinearLayout>
完整代码
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <data> <import type="com.leavesc.databinding_demo.model.User" /> <variable name="userInfo" type="User" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="20dp" android:orientation="vertical" tools:context="com.leavesc.databinding_demo.Main2Activity"> <TextView android:id="@+id/tv_userName" ··· android:text="@{userInfo.name}" /> <TextView ··· android:text="@{userInfo.password}" /> </LinearLayout> </layout>
1.1.3 修改 MainActivity 类
在 Activity
中
- 通过
DataBindingUtil
设置布局文件 - 数据绑定对象
ActivityMainBinding
的实例名根据布局文件名来生成 - 数据绑定对象通过
setXXX
方法注入数据
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main); User user = new User("leavesC", "123456"); activityMainBinding.setUserInfo(user); }
1.2 响应式数据绑定
参考 Vue 响应式,
<template> <div class="container"> <span> {{data}} </span> </div> </template> <script lang="ts" setup> const data = ref('hello') </script>
只需要用 ref
包裹数据即可
而在 Android 中也需要用 ObservableField
模板类包装数据
这里定义一个 ObservableGoods
类型
public class ObservableGoods { public ObservableField<String> name; public ObservableField<Float> price public ObservableField<String> details; public ObservableGoods(String name, float price, String details) { this.name = new ObservableField<>(name); this.price = new ObservableField<>(price); this.details = new ObservableField<>(details); } }
同上注入数据即可
1.3 补充
1.3.1 Fragment
假设 Fragment
有布局文件 fragment_collection
,在 onCreateView
中
@Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { FragmentCollectionBinding binding = DataBindingUtil.inflate(inflater, R.layout.fragment_collection, container, false); return binding.getRoot(); }
1.3.2 替代 findViewById
假设在布局文件中有 id
为 tvUserName
的控件,获取控件可以
activityMainBinding.tvUserName.setText("Hello");
1.3.3 Observable 容器类
DataBinding
也提供了包装类用于替代原生的 List 和 Map,分别是 ObservableList 和 ObservableMap
当其包含的数据发生变化时,绑定的视图也会随之进行刷新
不过在布局文件声明中指定模板类型的时候需要转义符
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <data> <import type="android.databinding.ObservableList"/> <import type="android.databinding.ObservableMap"/> <variable name="list" type="ObservableList<String>"/> <variable name="map" type="ObservableMap<String,String>"/> <variable name="index" type="int"/> <variable name="key" type="String"/> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.leavesc.databinding_demo.Main12Activity"> <TextView android:padding="20dp" android:text="@{list[index],default=xx}"/> <TextView android:layout_marginTop="20dp" android:padding="20dp" android:text="@{map[key],default=yy}"/> </LinearLayout> </layout>