DataBinding
前言
时间: 23/09/18 (牢记 九·一八 事变)
AndroidStudio
版本: Giraffe 2022.3.1 JDK:17 开发语言: Kotlin
Gradle版本: 8.0 Gradle plugin Version: 8.1.1
概述
上一篇讲述了 ViewBinding 的使用,ViewBinding 能够简化绑定视图的代码。本篇就了解一下 DataBinding 组件,它和 ViewBinding 一样,也可以引用视图的 id 来实现交互,但是 DataBinding 有更加丰富的功能。其次 DataBinding 也是实现MVVM
框架的重要组件之一。
DataBinding 的基本使用
简单的视图绑定功能
-
添加配置
在build.gradle(app)中添加
groovyandroid { ... ... buildFeatures { dataBinding = true } }
-
修改 Layout.xml 文件
在最新版本的 Gradle 中,使用 DataBinding 必须要给布局文件添加
<layout>
标签。否则无法正常build工程。在 xml 文件最外围添加 layout 标签
xml<?xml version="1.0" encoding="utf-8"?> <layout xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> 如果只使用viewbinding的功能,data标签可加可不加 </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> ... ... </androidx.constraintlayout.widget.ConstraintLayout> </layout>
-
在 Activity 中的修改和使用 ViewBinding 是一致的
添加一个全局 ActivityMainBinding 变量,inflate 实例化即可使用
kotlinclass MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) } }
数据视图单向绑定
-
给上面提到的 xml 中添加的
<data>
标签添加属性xml<data> <variable name="point" type="Int" /> </data>
name 就是后续需要调用的,类似于代码中的变量名,而type 就是 name 的类型。
当然也可以使用自定义的实体类。
xml<data> <variable name="user" type="com.example.part_6.entity.User" /> </data>
定义了一个User类,名称为 user 。
kotlindata class User(var id: String, var name: String)
-
在 xml 中的TextView视图控件中添加 @{}
xml<TextView android:id="@+id/tv_username" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.name}" android:textSize="24sp" /> <TextView android:id="@+id/tv_id" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.id}" android:textSize="18sp" /> <androidx.appcompat.widget.AppCompatButton android:id="@+id/submit_info" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="submit" android:layout_marginTop="38dp" />
添加一个按钮,点击响应相关事件实现单向绑定。具体的布局可以自己写,我这边省略了布局控制相关的代码。需要demo源码请在文末获取。
-
在 Activity 中进行数据绑定
kotlin//MainActivity class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) binding.submitInfo.setOnClickListener { val id = binding.etId.text.toString().trim() val name = binding.etUsername.text.toString().trim() val user = User(id, name) binding.user = user //只需要将user数据传给<data>,在xml中会自动分配user.name和user.id } } }
单向绑定结果图
数据视图双向绑定
这是实现
MVVM
的关键,感兴趣的可以仔细看看。
上面的例子呢,需要点击按钮,响应后读取edit中的数据,然后通过单向绑定将 数据 传给 text_view 。我们能否省略这个点击后获取数据的步骤呢?Of course yes. 并且方案不止一种,我们可以给Edit_Text添加数据变化监听,但是这种方式不涉及databinding,这里就不细说了,具体可以查一查 addTextChangedListener 这个API。
而双向绑定就是更为便捷,代码更简单的一种方式。
-
新建一个 UserBind 继承
BaseObservable()
,给属性的 getter 添加 Bindable 注释,并给setter添加 notifyPropertyChanged 方法。kotlinclass UserBind: BaseObservable() { @get:Bindable var name: String = "" set(value) { field = value notifyPropertyChanged(BR.name) } @get:Bindable var id: String = "" set(value) { field = value notifyPropertyChanged(BR.id) } }
BaseObservable
是一种可观察数据,继承自它的数据类负责在更新是发出通知。 -
更改 xml 中 EditText 的 text 属性为 @={}
xml... <com.google.android.material.textfield.TextInputEditText android:id="@+id/et_username" android:hint="Text user name" android:text="@={userBind.name}" android:layout_width="match_parent" android:layout_height="wrap_content" /> ... <com.google.android.material.textfield.TextInputEditText android:id="@+id/et_id" android:hint="Text user id" android:text="@={userBind.id}" android:inputType="number" android:layout_width="match_parent" android:layout_height="wrap_content" />
-
在 Activity 中绑定 UserBind 对象
kotlinclass MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) val userBind = UserBind() binding.userBind = userBind } }
-
结果图
以上是使用BaseObservable来实现的 双向数据绑定,使用 BR 需要引入 kapt 插件
groovy
plugins {
id("com.android.application")//default
id("org.jetbrains.kotlin.android")//default
id("kotlin-kapt")//this one
}
使用 DataBinding 绑定点击事件
相信很多人使用点击事件时,或多或少都用到过onClick属性,然后在Activity中添加一个与onClick属性同名的函数来实现点击事件响应。而databinding的绑定点击事件其实和这个方法非常相似。
-
添加一个ClickHandler类
kotlinclass ClickHandler { val TAG = "ClickHandler" fun click1(view: View) { Log.d(TAG, "click1") } }
-
layout中引入这个类
xml... <data> ... <variable name="clickHandler" type="com.example.part_6.ClickHandler" /> </data> .... .... <androidx.appcompat.widget.AppCompatButton android:id="@+id/click1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="50dp" android:onClick="@{clickHandler::click1}" android:text="click1" />
-
然后在Activity中绑定这个类和视图
kotlinclass MainActivity : AppCompatActivity() { private val TAG = "MainActivity" private lateinit var binding: ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) //click bind binding.clickHandler = ClickHandler() } }
-
log
在现在的版本还有更高级的方法,这种方法可以传参数
-
添加一个方法到ClickHandler中
kotlinfun click2(view: View, userBind: UserBind) { Log.d(TAG, "click2: user = $userBind") }
-
修改 layout 中的 onClick属性
xmlandroid:onClick="@{(view) -> clickHandler.click2(view, userBind)}"
-
Log
这种方式可以从代码中抽离部分代码到 xml 中,但是在实际开发过程中,我们的点击事件监听器可能会比较复杂,这会导致代码臃肿。所以复杂的监听器还是可以根据个人分模块或多方法实现。
总结
这节主要讲述的DataBinding
的基本用法,包括单向绑定、双向绑定以及点击监听绑定。
当然,DataBinding 能实现的功能远不止于此,关于 DataBinding 的进阶用法,可以查阅相关资料。后续我也会再写一个关于jetpack进阶用法的专栏。
下节就讲述一下jetpack的数据库操作的组件 ------ room