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)

相关推荐
传奇开心果编程12 小时前
【Compose Multiplatform 跨端开发学与练】第3课 布局与组件
android·windows·学习·ui·ios·kotlin·composer
事圆则缓13 小时前
Kotlin 入门与面试:从空安全、扩展函数到协程
安全·面试·kotlin
传奇开心果编程14 小时前
【现代声明式UI学与练】第9课 性能优化——渲染优化、列表优化、内存优化、启动优化
学习·flutter·react native·ui·性能优化·swiftui·android jetpack
传奇开心果编程14 小时前
【Compose Multiplatform 跨端开发学与练】第8课 资源管理与主题
android·windows·学习·ios·kotlin·web·composer
传奇开心果编程16 小时前
【Compose Multiplatform 跨端开发学与练】第9课 测试与调试
android·学习·macos·ios·kotlin·web·composer
传奇开心果编程16 小时前
【Compose Multiplatform 跨端开发学与练】第4课 导航与路由
android·windows·学习·ui·ios·kotlin·composer
传奇开心果编程16 小时前
【Compose Multiplatform 跨端开发学与练】第6课 状态管理与架构
android·学习·ui·ios·架构·kotlin·composer
传奇开心果编程17 小时前
【Compose Multiplatform 跨端开发学与练】第2课 Compose 基础语法
android·windows·学习·ui·ios·kotlin·composer
熊猫钓鱼>_>1 天前
Kotlin Multiplatform for OpenHarmony 实战:为 Reaktive 实现响应式原语适配(完整版 · 含摘要目录与技术图表)
华为·kotlin·大模型·ai编程·harmonyos·适配·reaktive
李游Leo2 天前
HarmonyOS 7 InsightBoard 多形态适配实录 06:ArkUI × 多设备回归:布局抖动、监听释放与全形态验收【鸿蒙心迹】
回归·kotlin·harmonyos