Android 数据绑定简单使用
Contents
Android 数据绑定简单使用
这次我们要替代获取控件的方法,以前是使用 findViewById
一个一个拿到控件
现在我们需要直接在 layout
中注入数据对象,我们还要直接通过 id
访问到控件
数据绑定
启用数据绑定
在 build.gradle
中添加如下代码
android {
dataBinding {
enable = true
}
}
即可开启数据绑定
修改布局文件
先看 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>
修改 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);
}
响应式数据绑定
参考 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);
}
}
同上注入数据即可
补充
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();
}
替代 findViewById
假设在布局文件中有 id
为 tvUserName
的控件,获取控件可以
activityMainBinding.tvUserName.setText("Hello");
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>