Jetpack系列(五) -- DataBinding

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)中添加

    groovy 复制代码
    android {
        ...
        ...
    	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 实例化即可使用

    kotlin 复制代码
    class 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 。

    kotlin 复制代码
    data 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 方法。

    kotlin 复制代码
    class 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 对象

    kotlin 复制代码
    class 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类

    kotlin 复制代码
    class 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中绑定这个类和视图

    kotlin 复制代码
    class 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中

    kotlin 复制代码
        fun click2(view: View, userBind: UserBind) {
            Log.d(TAG, "click2: user = $userBind")
        }
  • 修改 layout 中的 onClick属性

    xml 复制代码
    android:onClick="@{(view) -> clickHandler.click2(view, userBind)}"
  • Log

这种方式可以从代码中抽离部分代码到 xml 中,但是在实际开发过程中,我们的点击事件监听器可能会比较复杂,这会导致代码臃肿。所以复杂的监听器还是可以根据个人分模块或多方法实现。

总结

这节主要讲述的DataBinding的基本用法,包括单向绑定、双向绑定以及点击监听绑定。

当然,DataBinding 能实现的功能远不止于此,关于 DataBinding 的进阶用法,可以查阅相关资料。后续我也会再写一个关于jetpack进阶用法的专栏。

下节就讲述一下jetpack的数据库操作的组件 ------ room

demo地址(GitHub)

相关推荐
xvch4 小时前
Kotlin 2.1.0 入门教程(五)
android·kotlin
xvch8 小时前
Kotlin 2.1.0 入门教程(七)
android·kotlin
zhangphil10 小时前
Android BitmapShader简洁实现马赛克,Kotlin(一)
android·kotlin
五味香17 小时前
Java学习,查找List最大最小值
android·java·开发语言·python·学习·golang·kotlin
五味香2 天前
Java学习,List截取
android·java·开发语言·python·学习·golang·kotlin
xvch2 天前
Kotlin 2.1.0 入门教程(三)
android·kotlin
小李飞飞砖2 天前
kotlin的协程的基础概念
开发语言·前端·kotlin
深色風信子3 天前
Kotlin Bytedeco OpenCV 图像图像49 仿射变换 图像裁剪
opencv·kotlin·javacpp·bytedeco·仿射变换 图像裁剪
五味香3 天前
Java学习,List移动元素
android·java·开发语言·python·学习·kotlin·list
普通网友3 天前
Android-Jetpack架构组件(一)带你了解Android-Jetpack
jvm·架构·android jetpack