一、优势
1、数据双向绑定允许 UI 组件和数据模型之间直接关联,从而减少了大量的手动更新操作
2、为MVVM打好基础
二、简单解释什么是双向绑定
如果您学过前端Vue,相信你已经比较清楚这个概念。
先看什么是单向,单向绑定就是将数据直接给到UI显示,当数据发生变化时,UI不会主动更新。例如,获取传感器温度,1s传感器返回 10条数据,每次接收到数据都要对UI进行手动更新操作,操作会过于频繁。
如果是双向绑定呢,双向绑定,当数据发生变化时,UI会实时更新。
三、具体实现
1、准备工作
新建项目后,在buildgradle.kts (Module级别),添加如下代码:
buildFeatures{
viewBinding = true
dataBinding = true
}
viewBinding = true:启用 View Binding,这是 Android 提供的一种用于安全地访问布局中视图的机制。不需要使用 findViewById()
dataBinding = true:启用 Data Binding,允许你在布局 XML 中绑定数据对象,并支持单向或双向数据绑定。
2、viewmodel准备
// 声明 ViewModel 类,用于保存 UI 数据并在配置变化(如旋转屏幕)时保留数据
class DataViewModel : ViewModel() {
// 定义一个可变的 LiveData,用于保存用户输入的昵称
// MutableLiveData 是 LiveData 的子类,支持读写
// 初始值设置为 ""(空字符串),避免 null 值导致 UI 显示异常
val name = MutableLiveData<String>("")
}
3、xml的规范以及编写
写法 | 类型 | 含义 |
---|---|---|
@{viewModel.name} | 单向绑定 | 数据从 viewModel.name 流向 UI(UI 会随着数据变化自动更新) |
@={viewModel.name} | 双向绑定 | 数据和 UI 之间 双向同步(数据变了 UI 会变,UI 变了数据也会跟着变) |
在使用 Data Binding 的时候,最外层只能是 <layout>
标签,这是 Data Binding 的语法规范。
<layout ...>
<data>
...
</data>
<!-- 实际的布局根节点,例如 ConstraintLayout、LinearLayout、RelativeLayout 等 -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 你的控件 -->
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="viewModel"
type="com.example.databinding.DataViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="24dp">
<EditText
android:id="@+id/editTextName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="请输入昵称"
android:text="@={viewModel.name}"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:id="@+id/textViewResult"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{"你好," + viewModel.name}'
android:textSize="20sp"
app:layout_constraintTop_toBottomOf="@id/editTextName"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="16dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
4、Activity的编写
class MainActivity : AppCompatActivity() {
// 使用 ViewBinding 自动生成的绑定类,用于访问布局中的视图
private lateinit var binding: ActivityMainBinding
// 声明 ViewModel,用于存储和管理 UI 相关的数据
private lateinit var viewModel: DataViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 启用沉浸式状态栏(Android 13+ 的边缘到边缘布局)
enableEdgeToEdge()
// 初始化 ViewBinding(ActivityMainBinding 是根据 activity_main.xml 自动生成的)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// 获取 ViewModel 实例,作用域为当前 Activity
viewModel = ViewModelProvider(this)[DataViewModel::class.java]
// 将 ViewModel 绑定到 XML 中的 `viewModel` 变量(用于数据绑定)
binding.viewModel = viewModel
// 设置 lifecycleOwner,LiveData 才能感知生命周期并自动更新 UI
binding.lifecycleOwner = this
}
}
四、效果展示
没有任何操作时的显示
下面通过键盘打字,底部输出会自动更新
最后,是不是非常不错 呢!