Android中Jetpack组件DataBinding使用详解

14 篇文章 0 订阅
9 篇文章 1 订阅

1.DataBindingxml文件中的使用

  • 首先打开dataBinding开关

    使用DataBinding首先在build.gradle文件中开启Databinding

    同时开启viewBinding,需要能自动生成xmlViewbinding文件

    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类被多个variabletype属性用到则可以通过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对象,是通过xmlvariable标签的name属性定义的infobean

	activityMainBinding.infoBean = userBean

2.DataBinding单向数据绑定

  • 首先需要在build.gradle中增加包,plugins中增加kotlin-kaptkotlin-parcelize
plugins {
    id 'kotlin-kapt'
    id 'kotlin-parcelize'
}
  • UserBean类中需要进行改造

    1. 继承BaseObservable()

    2. 针对要绑定的变量进行@Bindable注解的声明

    3. 针对每个绑定变量重写set方法,通过通过valuefield赋值

      针对var属性setget方法是默认存在的,所以是对set进行重写

    4. 对持有的当前对象中的属性变化就行通知更新

      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双向数据绑定

  • 数据双向绑定

    xmlview的变化通过@={}进行绑定,对数据逆向赋值

  • 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>
  • ActivityonCreate()方法中实现

    重点是databind.userBeanDemo1 = userBean语句的调用

        var databind: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        var userBean = UserBean()
		//通过给userBeanDemo1的赋值,才能进行代码与xml的双向绑定
        databind.userBeanDemo1 = userBean

3.DataBinding监听事件的绑定

  1. 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)
            }
        }
    }
    
  2. 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>
    
  3. ActivityonCreate()方法内的实现

    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") }
    
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值