深入解析 androidx.databinding.BaseObservable

# 深入解析 androidx.databinding.BaseObservable

在现代 Android 开发中,数据绑定 (Data Binding) 是一个重要的技术,它简化了 UI 和数据之间的交互。在数据绑定框架中,androidx.databinding.BaseObservable 是一个关键类,用于实现可观察的数据模型。本文将详细介绍 BaseObservable 的用法和原理,帮助你更好地掌握数据绑定技术。

什么是 BaseObservable?

BaseObservable 是一个基础类,它实现了 Observable 接口,使得数据模型能够被观察。当数据模型中的属性发生变化时,BaseObservable 可以通知所有的观察者(通常是绑定的 UI 视图)自动更新。

基本用法

创建一个继承自 BaseObservable 的类

要使用 BaseObservable,我们需要创建一个继承自 BaseObservable 的类,并在需要通知变化的属性上添加 @Bindable 注解。然后,在属性的 setter 方法中调用 notifyPropertyChanged 方法。

下面是一个简单的示例,展示如何创建一个用户类,并使用 BaseObservable@Bindable 实现数据绑定:

import androidx.databinding.BaseObservable
import androidx.databinding.Bindableclass User : BaseObservable() {var firstName: String = ""@Bindable get() = fieldset(value) {field = valuenotifyPropertyChanged(BR.firstName)}var lastName: String = ""@Bindable get() = fieldset(value) {field = valuenotifyPropertyChanged(BR.lastName)}
}

在这个示例中,User 类继承自 BaseObservable,并且使用 @Bindable 注解标记了 firstNamelastName 属性。当这些属性的值发生变化时,notifyPropertyChanged 方法会通知数据绑定框架更新 UI。

在布局文件中使用数据绑定

接下来,我们需要在布局文件中使用数据绑定。首先,在项目的 build.gradle 文件中启用数据绑定:

android {...dataBinding {enabled = true}
}

然后,在布局文件中使用数据绑定。在根布局中添加 layout 标签,并声明一个 User 类型的变量:

<layout xmlns:android="http://schemas.android.com/apk/res/android"><data><variablename="user"type="com.example.app.User" /></data><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="@={user.firstName}" /><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="@={user.lastName}" /></LinearLayout>
</layout>

在 Activity 或 Fragment 中绑定数据

最后,在 ActivityFragment 中绑定数据并设置视图模型:

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.example.app.databinding.ActivityMainBindingclass MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)val user = User().apply {firstName = "John"lastName = "Doe"}binding.user = user}
}

深入理解 BaseObservable 的工作原理

BaseObservable 的核心在于它实现了 Observable 接口,并且提供了一组方法,用于管理观察者和通知属性变化。

notifyPropertyChanged 方法

notifyPropertyChanged 方法用于通知数据绑定框架某个属性的值发生了变化。我们需要在属性的 setter 方法中调用它,并传递相应的属性 ID。例如:

var firstName: String = ""@Bindable get() = fieldset(value) {field = valuenotifyPropertyChanged(BR.firstName)}

notifyChange 方法

如果多个属性的值发生了变化,或者我们想要一次性通知所有的绑定属性发生了变化,可以使用 notifyChange 方法:

fun updateUser(firstName: String, lastName: String) {this.firstName = firstNamethis.lastName = lastNamenotifyChange()
}

自动生成的 BR 类

当我们在属性上添加 @Bindable 注解时,数据绑定框架会自动生成一个 BR 类。这个类包含了所有绑定属性的 ID,用于在属性值变化时通知数据绑定框架。例如,BR.firstNameBR.lastName 就是自动生成的 ID。

object BR {@JvmFieldval _all = 0@JvmFieldval firstName = 1@JvmFieldval lastName = 2
}

高级用法

双向数据绑定

双向数据绑定允许我们在视图和数据模型之间实现双向同步。例如,当用户在 EditText 中输入文本时,数据模型会自动更新;同样,当数据模型的值发生变化时,视图也会自动更新。我们可以通过在 XML 中使用 @= 语法来实现双向数据绑定:

<EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="@={user.firstName}" />

自定义属性和 BindingAdapter

有时候,我们需要在视图上绑定一些自定义属性。为此,我们可以使用 BindingAdapter 注解来自定义数据绑定逻辑。例如,我们可以为 ImageView 创建一个自定义绑定适配器,用于加载网络图片:

import android.widget.ImageView
import androidx.databinding.BindingAdapter
import com.bumptech.glide.Glideobject BindingAdapters {@JvmStatic@BindingAdapter("imageUrl")fun loadImage(view: ImageView, url: String?) {if (!url.isNullOrEmpty()) {Glide.with(view.context).load(url).into(view)}}
}

在布局文件中使用自定义属性:

<ImageViewandroid:layout_width="match_parent"android:layout_height="wrap_content"app:imageUrl="@{viewModel.imageUrl}" />

性能优化

在使用数据绑定时,我们需要注意性能优化,特别是在大型项目中。以下是一些常见的优化建议:

使用 ObservableField

对于简单的单个字段绑定,可以使用 ObservableField 来代替 @Bindable 注解和 BaseObservable,这样可以减少代码量并提高性能:

import androidx.databinding.ObservableFieldclass User {val firstName = ObservableField<String>()val lastName = ObservableField<String>()
}

避免过度绑定

绑定的数据越多,数据绑定框架的开销就越大。尽量只绑定必要的数据,避免不必要的绑定和数据刷新。

结论

BaseObservable 是 Android 数据绑定框架中的一个重要组件,通过它可以实现数据和视图的双向绑定,从而简化代码结构,提高代码的可维护性。通过本文的介绍,相信你已经对 BaseObservable 的基本用法、高级用法和性能优化有了更深入的了解。在实际开发中,合理使用 BaseObservable 和数据绑定框架,可以大大提升开发效率和应用的用户体验。

Best regards!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/366641.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 代码块

Java中的代码块主要有三种类型&#xff1a;普通代码块、静态代码块、构造代码块。它们的用途和执行时机各不相同。 普通代码块&#xff1a;在方法内部定义&#xff0c;使用一对大括号{}包围的代码片段。它的作用域限定在大括号内&#xff0c;每当程序执行到该代码块时就会执行其…

Pikachu 不安全的文件下载(Unsafe file download)概述 附漏洞利用案例

目录 获取下载链接 修改链接 重新构造链接 拓展 不安全的文件下载概述 文件下载功能在很多web系统上都会出现&#xff0c;一般我们当点击下载链接&#xff0c;便会向后台发送一个下载请求&#xff0c;一般这个请求会包含一个需要下载的文件名称&#xff0c;后台在收到请求…

初识Java(复习版)

一. 什么是Java Java是一种面向对象的编程语言&#xff0c;和C语言有所不同&#xff0c;C语言是一门面向过程的语言。偏底层实现&#xff0c;比较注重底层的逻辑实现。不能一味的说某一种语言特别好&#xff0c;每一种语言都是在特定的情况下有自己的优势。 二.Java语言发展史…

Docker Compose 一键快速部署 RocketMQ

Apache RocketMQ是一个开源的分布式消息中间件系统&#xff0c;最初由阿里巴巴开发并贡献给Apache软件基金会。RocketMQ提供了高性能、高可靠性、高扩展性和低延迟的消息传递服务&#xff0c;适用于构建大规模分布式系统中的消息通信和数据同步。 RocketMQ支持多种消息模型&am…

武汉星起航:无锡跨境电商加速“出海”,物流升级助品牌全球布局

随着全球化的不断深入&#xff0c;跨境电商作为数字外贸的新业态&#xff0c;正逐渐成为无锡企业拓展海外市场的重要渠道。武汉星起航关注到&#xff0c;近年来&#xff0c;无锡市通过积极推进国际物流枢纽建设&#xff0c;完善海外仓布局&#xff0c;以及各特色产业带的积极参…

JavaMySQL 学习(基础)

目录 Java CMD Java发展 计算机存储规则 Java学习 switch新用法&#xff08;可以当做if来使用&#xff09; 数组定义 随机数 Java内存分配 MySQL MySQL概述 启动和停止 客户端连接 数据模型 关系型数据库 SQL SQL通用语法 SQL分类 DDL--数据定义语言 数据库…

Intellij Idea显示回退和前进按钮的方法

方法1 使用快捷键&#xff1a; 回到上一步 ctrl alt <-&#xff08;左方向键&#xff09;回到下一步 ctrl alt ->&#xff08;右方向键&#xff09; 方法2&#xff1a; Preferences -> Appearance & Behavior -> Menus and Toolbars -> Navigation B…

SEO与AI的结合:如何用ChatGPT生成符合搜索引擎优化的内容

在当今数字时代&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;已成为每个网站和内容创作者都必须掌握的一项技能。SEO的主要目标是通过优化内容&#xff0c;使其在搜索引擎结果页面&#xff08;SERP&#xff09;中排名更高&#xff0c;从而吸引更多的流量。然而&#xf…

如何养成爱自己的习惯:吸引世间美好,改变命运

在这个快节奏、高压力的时代&#xff0c;我们常常被各种事务所困扰&#xff0c;内心难以得到真正的宁静。然而&#xff0c;古老的智慧告诉我们&#xff0c;“静”是宇宙万物的根源&#xff0c;是生命恢复的根本。本文将探讨如何养成“静”的习惯&#xff0c;从而吸引世间美好&a…

springboot项目jar包修改数据库配置运行时异常

一、背景 我将软件成功打好jar包了&#xff0c;到部署的时候发现jar包中数据库配置写的有问题&#xff0c;不想再重新打包了&#xff0c;打算直接修改配置文件&#xff0c;结果修改配置后&#xff0c;再通过java -jar运行时就报错了。 二、问题描述 本地项目是springBoot项目…

Efuse介绍及安全启动浅析

Efuse是什么 eFuse(electronic fuse): 电子保险丝&#xff0c;熔丝性的一种器件&#xff0c;属于一次性可编程存储器。 之所以称为eFuse&#xff0c;因为其原理像电子保险丝一样&#xff0c;CPU出厂后&#xff0c;这片eFuse控件内所有比特全为1&#xff0c;如果向一位bit写入…

Windows编程上

Windows编程[上] 一、Windows API1.控制台大小设置1.1 GetStdHandle1.2 SetConsoleWindowInfo1.3 SetConsoleScreenBufferSize1.4 SetConsoleTitle1.5 封装为Innks 2.控制台字体设置以及光标调整2.1 GetConsoleCursorInfo2.2 SetConsoleCursorPosition2.3 GetCurrentConsoleFon…

python本学期所有代码!

第一单元 ----------------------------------------------------------------------- #圆面积的计算 radius 25 area 3.1415 * radius * radius print(area) print("{:.2f}".format(area)) --------------------------------------------------------------------…

AI图生视频工具测试

环境&#xff1a; 即梦 pika LUMA 可灵 问题描述&#xff1a; AI图生视频工具测试下面是原图 解决方案&#xff1a; 1.即梦 效果 2.pika 生成效果 3.LUMA 生成效果还行 4.可灵 生成效果最好

Redis缓存管理机制

在当今快节奏的数字世界中&#xff0c;性能优化对于提供无缝的用户体验至关重要。缓存在提高应用程序性能方面发挥着至关重要的作用&#xff0c;它通过将经常使用或处理的数据存储在临时高速存储中来减少数据库负载并缩短响应时间&#xff0c;从而减少系统的延迟。Redis 是一种…

【有为己之心方能克己】

私欲会让人难受&#xff0c;为了自己舒服而去拔除&#xff0c;去除私欲小我&#xff0c;就可以为自己展现大我 “人不为己天诛地灭”&#xff0c;其实这句话不是自私自利的意思&#xff0c; 原意是&#xff1a;人如果不修为自己&#xff0c;不为那个真己而活&#xff0c;不活出…

【设计模式】【行为型模式】【责任链模式】

系列文章目录 可跳转到下面链接查看下表所有内容https://blog.csdn.net/handsomethefirst/article/details/138226266?spm1001.2014.3001.5501文章浏览阅读2次。系列文章大全https://blog.csdn.net/handsomethefirst/article/details/138226266?spm1001.2014.3001.5501 目录…

Java 微信小程序自建平台开发票保存到微信卡包

Java 微信小程序自建平台开发票保存到微信卡包 1 获取Access token2 获取自身的开票平台识别码3 设置商户联系方式4 获取授权页ticket5 获取授权页链接6 小程序打开授权页7 收取授权完成事件推送8 创建发票卡券模板9 上传PDF10 将电子发票卡券插入用户卡包 1 获取Access token …

分文件编译(简单学生系统)

定义学生基本信息 ①输出所有学生信息 ②删除某个学生后&#xff0c;输出所有学生信息 ③修改某个学生信息后&#xff0c;输出所有学生信息 ④查找某个学生的信息 main.c #include"k11*.h" int main(int argc, const char *argv[]) {struct student p[4]{{"…

3.js - 纹理的 magfilter、minFilter、各向异性过滤(各项异性解决倾斜模糊问题)

效果图&#xff0c;就是一个PlaneGeometry&#xff0c;加了一个贴图&#xff0c;再设置下面这些属性&#xff0c;你就放大缩小着看吧&#xff0c;反正我看不出什么来 代码 // ts-nocheck // 引入three.js import * as THREE from three // 导入轨道控制器 import { OrbitContro…