1.DataBinding
在xml
文件中的使用
-
首先打开
dataBinding
开关使用
DataBinding
首先在build.gradle
文件中开启Databinding
同时开启
viewBinding
,需要能自动生成xml
的Viewbinding
文件
android {
dataBinding {
enabled = true
}
//或者
buildFeatures {
viewBinding true
dataBinding true
}
}
-
布局中添加
<layout>
标签打开布局文件在布局文件的根布局中
alt+回车
,选择Convert to data binding 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"
xmlns:tools="http://schemas.android.com/tools">
<data>
</data>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
</android.support.constraint.ConstraintLayout>
</layout>
- 创建activity_main.xml文件完整代码
<?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"
xmlns:tools="http://schemas.android.com/tools">
<!--data标签中的class名称可以自定义,为代码中使用的viewbinding文件名称-->
<data class="ActivityMainBinding">
<!--1:默认使用UserBean类情况-->
<variable
name="userBeanDemo1"
type="com.jetpack.demo.UserBean" />
<!-- ·················分割线·············· -->
<!--2:通过alias配置UserBean的别名为bean-->
<import
alias="Bean"
type="com.jetpack.demo.UserBean" />
<!--通过2,alias配置的别名bean,配置userBeanDemo2-->
<variable
name="userBeanDemo2"
type="Bean" />
<!-- ·················分割线·············· -->
<!--4:通过import导入UserBean类-->
<import type="com.jetpack.demo.UserBean" />
<!--通过4,配置userBeanDemo3-->
<variable
name="userBeanDemo3"
type="UserBean" />
<!-- 通过UserBean导入UserListener -->
<variable
name="userListenerDemo4"
type="UserBean.UserListener" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按钮1" />
<Button
android:id="@+id/btn_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按钮2" />
<EditText
android:id="@+id/et_1"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:hint="输入内容" />
<TextView
android:id="@+id/tv_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>
</layout>
- 创建
UserBean
类
class UserBean {
var name: String = "user name"
var school: String = "school name"
var age: Int = 10
var sex: String = "男"
var address: String = "地址"
class UserListener {
fun userClick() {
Log.i("tag", "--->>userClick")
}
fun userClick(userBean: UserBean) {
Log.i("tag", "--->>" + userBean.name)
}
}
}
以上为activity_main
文件与UserBean
类两个文件
-
布局中定义需要的类名
在
data
标签中声明xml
中要使用的变量名和导入类的名称
<data>
<variable
name="userBeanDemo1"
type="com.jetpack.demo.UserBean" />
</data>
-
如果
Userbean
类被多个variable
的type
属性用到则可以通过import
标签导入示例代码如下:
<data>
<import
type="com.jetpack.demo.UserBean" />
<variable
name="userBeanDemo2"
type="UserBean" />
<variable
name="userBeanDemo3"
type="UserBean" />
</data>
-
如
UseBean
存在相同名称不同路径,则通过alias
定义别名示例代码如下:
<data>
<import
alias="Bean1"
type="com.jetpack.demo1.UserBean" />
<import
alias="Bean2"
type="com.jetpack.demo2.UserBean" />
<variable
name="demo1"
type="Bean1" />
<variable
name="demo2"
type="Bean2" />
</data>
-
data
标签中的class
属性,用来自定义代码中Activity
中的ViewBinding
使用的<ActivityMainBinding>
的名称,如定义成
ActivityMainBinding
示例代码如下:
<data class="ActivityMainBinding">
<import type="com.org.UserBean"/>
<import alias="TempUser" type="com.org.other.UserBean" />
<variable
name="bean"
type="UserBean"/>
<variable
name="infoBean"
type="UserBean"/>
<variable
name="userTemp"
type="UserBean"/>
</data>
-
DataBinding
在控件中的使用xml
中通过default
设置默认名称设置这个
default
的值应该是只在AS
预览布局文件时展示,App
中安装后并不展示这个值,由于userInfo
类中会有默认值
//大括号中进行表达式的展示
android:text="@{infoBean.school}"
//大括号中也可以写代码
android:text="@{String.valueOf(infoBean.school), default=默认名称}"
onCreate()
中通过调用DataBindingUtil.setContentView
代替setContentView()
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
var activityMainBinding = DataBindingUtil.setContentView<ActivityMainBinding>(this,R.layout.activity_main);
//与上行代码等同
//val binding: BindClass = DataBindingUtil.setContentView(this, R.layout.activity_databinding)
var userBean = UserBean();
activityMainBinding.infoBean = userBean
}
-
调用以下语句以后,界面会自动将
UserBean
中的值,赋值显示到页面上,如果不调用页面则显示值为null
此处调用的
infobean
对象,是通过xml
中variable
标签的name
属性定义的infobean
activityMainBinding.infoBean = userBean
2.DataBinding
单向数据绑定
- 首先需要在
build.gradle
中增加包,plugins
中增加kotlin-kapt
和kotlin-parcelize
plugins {
id 'kotlin-kapt'
id 'kotlin-parcelize'
}
-
UserBean
类中需要进行改造-
继承
BaseObservable()
-
针对要绑定的变量进行
@Bindable
注解的声明 -
针对每个绑定变量重写
set
方法,通过通过value
给field
赋值针对
var
属性set
与get
方法是默认存在的,所以是对set
进行重写 -
对持有的当前对象中的属性变化就行通知更新
notifyPropertyChanged(BR.school)
//只通知school
变量notifyChange()
//全局刷新通知
-
class UserBean : BaseObservable() {
//school与name两个变量是针对单向数据绑定的实现
@Bindable
var school: String = "school name"
set(value) {
field = value
//只通知有school变量变化的
notifyPropertyChanged(BR.school)
}
@Bindable
var name: String = "user name"
set(value) {
field = value
//全局进行通知
notifyChange()
}
var sex: String = "男"
var age: Int = 10
var address: String = "地址"
}
- 以后只要改变
UserBean
对象中的属性值,就会改变xml文件中的属性
userBean.school = "school 2"
注意:上面单向绑定的存在弊端,实现过程很麻烦,实际使用中有更简单的方式
上述方式在实现过程中需要重写set
方法,比较麻烦,谷歌官方有另一种单向数据绑定实现方式,对UserBean
类进行改造
-
如果属性需要传入默认值的话,可以在
ObservableField()
方法中传入参数默认值值的参数类型根据泛型决定
简单方式中不需要继承
BaseObservable()
不需要
Bindable
注解属性通过
ObservableField
实现
class UserBean : BaseObservable() {
/**
school,age,name为单向数据绑定的简单示例
*/
var school: ObservableField<String> = ObservableField("school name")
var age: ObservableField<Int> = ObservableField(10)
var name: ObservableField<String> = ObservableField("user name")
var sex: String = "男"
var address: String = "地址"
}
-
通过继承
ObservableField
类后需要注意UserBean
中的属性与方法进行赋值与取值的时候需要通过调用set()
与get()
方法不能直接
userBean.school = "school name"
这样调用
var userBean = UserBean()
//如果UserBean继承BaseObservable类后需要如下调用
userBean.school.set("middle school")
3.DataBinding
双向数据绑定
-
数据双向绑定
xml
的view
的变化通过@={}
进行绑定,对数据逆向赋值 -
xml
文件中的内容
<?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"
xmlns:tools="http://schemas.android.com/tools">
<data class="ActivityMainBinding">
<variable
name="userBeanDemo1"
type="com.jetpack.demo.UserBean" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{userBeanDemo1.school, default=默认名称}"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/et_1"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:hint="输入学校名称"
android:text="@={userBeanDemo1.school}" />
</LinearLayout>
</layout>
-
Activity
的onCreate()
方法中实现重点是
databind.userBeanDemo1 = userBean
语句的调用
var databind: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
var userBean = UserBean()
//通过给userBeanDemo1的赋值,才能进行代码与xml的双向绑定
databind.userBeanDemo1 = userBean
3.DataBinding
监听事件的绑定
-
UserBean
中实现了监听回调的方法class UserBean : BaseObservable() { @Bindable var school: ObservableField<String> = ObservableField("school name") @Bindable var age: ObservableField<Int> = ObservableField(10) @Bindable var name: ObservableField<String> = ObservableField("user name") var sex: String = "男" var address: String = "地址" //传入的userBean定义为val class UserListener(val userBean: UserBean) { fun userClick(v: View) { Log.i("tag", "--->>userClick") userBean.school.set("学校改名") } fun userClick(userBean: UserBean) { Log.i("tag", "--->>" + userBean.name) } } }
-
xml
文件中实现<?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" xmlns:tools="http://schemas.android.com/tools"> <data class="ActivityMainBinding"> <variable name="userBeanDemo" type="com.jetpack.demo.UserBean" /> <variable name="userListenerDemo4" type="com.jetpack.demo.UserBean.UserListener" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="10dp" android:orientation="vertical" tools:context=".MainActivity"> <Button android:id="@+id/btn_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{userListenerDemo4.userClick}" android:text="点击修改学校名称" /> <TextView android:id="@+id/tv_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{userBeanDemo.school, default=默认名称}" android:textSize="20sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </LinearLayout></layout>
-
Activity
中onCreate()
方法内的实现var databind: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)var userBean = UserBean()databind.userBeanDemo1 = userBean//初始化userListenervar userListener = UserBean.UserListener(userBean)//给databind的listener赋值databind.userListenerDemo4 = userListener
4.点击事件的回调可以传入参数几种形式
第一种:
android:onClick="@{()->userListenerDemo4.userClickBean(userBeanDemo1)}"
方法的回调实现
fun userClickBean(userBean: UserBean) { Log.i("tag", "--->>" + userBean.school) userBean.school.set("学校改名") }
第二种:
android:onClick="@{()->userListenerDemo4.userClick()}"
kotlin
代码中回调方法实现fun userClick() { Log.i("tag", "--->>userClick>>") }
第三种:
android:onClick="@{userListenerDemo4.userClick}"android:onClick="@{userListenerDemo4::userClick}"
kotlin
代码中回调方法实现fun userClick(v: View) { Log.i("tag", "--->>userClick") }