深入解析 androidx.databinding.BaseObservable

news2024/11/18 21:39:10

# 深入解析 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.Bindable

class User : BaseObservable() {
    var firstName: String = ""
        @Bindable get() = field
        set(value) {
            field = value
            notifyPropertyChanged(BR.firstName)
        }

    var lastName: String = ""
        @Bindable get() = field
        set(value) {
            field = value
            notifyPropertyChanged(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>
        <variable
            name="user"
            type="com.example.app.User" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

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

        <EditText
            android: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.ActivityMainBinding

class 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() = field
    set(value) {
        field = value
        notifyPropertyChanged(BR.firstName)
    }

notifyChange 方法

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

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

自动生成的 BR 类

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

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

高级用法

双向数据绑定

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

<EditText
    android: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.Glide

object BindingAdapters {
    @JvmStatic
    @BindingAdapter("imageUrl")
    fun loadImage(view: ImageView, url: String?) {
        if (!url.isNullOrEmpty()) {
            Glide.with(view.context).load(url).into(view)
        }
    }
}

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

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

性能优化

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

使用 ObservableField

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

import androidx.databinding.ObservableField

class User {
    val firstName = ObservableField<String>()
    val lastName = ObservableField<String>()
}

避免过度绑定

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

结论

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

Best regards!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

雨量气象站:野外监测的得力助手

在广阔无垠的大自然中&#xff0c;雨量、风力、风向、温湿度以及大气压力等气象数据对于各种应用场景都至关重要。特别是在野外、森林防火、山洪监测等无市电供电的场合&#xff0c;一款高效可靠的监测设备更是不可或缺。雨量气象站正是为了满足这些需求而诞生的户外专用监测站…

昇思25天学习打卡营第8天|模型训练

昇思25天学习打卡营第8天|模型训练 前言模型训练构建数据集定义神经网络模型定义超参、损失函数和优化器超参损失函数优化器 训练与评估 个人任务打卡&#xff08;读者请忽略&#xff09;个人理解与总结 前言 非常感谢华为昇思大模型平台和CSDN邀请体验昇思大模型&#xff01;从…

剖析DeFi交易产品之UniswapV4:概述篇

本文首发于公众号&#xff1a;Keegan小钢 UniswapV4 与 UniswapV3 相比&#xff0c;算法上并没有什么改变&#xff0c;依然还是采用集中流动性模型&#xff0c;但架构上变化很大&#xff0c;包括功能架构&#xff0c;也包括技术架构。相比之前的版本&#xff0c;UniswapV4 最大…

光扩散微球市场增长空间大 我国已实现其产业化

光扩散微球市场增长空间大 我国已实现其产业化 光扩散微球是一种高性能微球材料&#xff0c;具有优异的光学和力学性能&#xff0c;且不含杂质&#xff0c;将其涂抹在光扩散膜&#xff08;板&#xff09;上&#xff0c;可以将点光源变成面光源&#xff0c;使显示面板的布光更加…

大型语言模型能否生成可信的事实核查解释?——通过多智能体辩论实现可信可解释的事实核查

Can LLMs Produce Faithful Explanations For Fact-checking? Towards Faithful Explainable Fact-Checking via Multi-Agent Debate 论文地址:https://arxiv.org/abs/2402.07401https://arxiv.org/abs/2402.07401 1.概述 在数字化时代,对于迅速传播的错误信息,其核实与明…

达梦数据库系列—19. 动态增加实时备库

目录 动态增加实时备库 1、数据准备 2 、配置新备库 2.1配置 dm.ini 2.2配置 dmmal.ini 2.3 配置 dmarch.ini 2.4 配置 dmwatcher.ini 2.5 启动备库 2.6 设置 OGUID 2.7 修改数据库模式 3、 动态添加 MAL 配置 4、 动态添加归档配置 5、 修改监视器 dmmonitor.ini…

windows离线安装显卡驱动解决方案

前言 我们说这个离线泛指计算机无公网环境&#xff0c;而我们需要将显卡驱动打上&#xff0c;既然没有公网&#xff0c;我们就无法使用联网的方式&#xff08;傻瓜式安装&#xff09;&#xff0c;受各种原因限制&#xff0c;也不可以把主机搬走连上互联网进行安装。总之…

导入tidb时将数据库表导出为多张csv格式

DBeaver&#xff1a; 步骤&#xff1a; 确定目标库——>工具——>创建新任务 NEXT Navicat&#xff1a;

AQS同步队列、条件队列源码解析

AQS详解 前言AQS几个重要的内部属性字段内部类 Node同步队列 | 阻塞队列等待队列 | 条件队列 重要方法执行链同步队列的获取、阻塞、唤醒加锁代码流程解锁 条件队列的获取、阻塞、唤醒大体流程 调用await()方法1. 将节点加入到条件队列2. 完全释放独占锁3. 等待进入阻塞队列4. …

智慧校园新气象:校园气象站

在数字化、智能化的浪潮下&#xff0c;传统校园正在迎来一场革命性的变革。在这场变革中&#xff0c;校园气象站以其独特的功能和魅力&#xff0c;成为推动校园气象科普教育、提升校园品质的重要力量。 一、校园气象站&#xff1a;智慧校园的“气象眼” 校园气象站&#xff0c…

UVa1321/LA2925 Dice contest

UVa1321/LA2925 Dice contest 题目链接题意分析测试数据AC 代码 题目链接 本题是2003年icpc欧洲区域赛中欧赛区的D题 题意 骰子的六面展开图如下&#xff0c;现在把骰子的六个面赋予一套权重 w i ( 1 ≤ w i ≤ 50 , 1 ≤ i ≤ 6 ) w_i(1\le w_i \le 50,1\le i\le 6) wi​(1≤…

如何选择适合您业务需求的多语言跨境电商系统源码

随着互联网技术的飞速发展和全球市场的日益融合&#xff0c;多语言跨境电商已经成为许多企业进军国际市场的重要战略。在这个竞争激烈的时代&#xff0c;拥有一个适合自己业务需求的多语言跨境电商系统源码至关重要。本篇文章将为您揭秘如何选择适合您业务需求的多语言跨境电商…

奥威BI零售数据分析的小心机:多维动态分析

多维动态分析&#xff0c;顾名思义&#xff0c;就是在多个维度上对数据进行灵活的、动态的分析。在零售业务中&#xff0c;这些维度可能包括商品、时间、地区、顾客群体等。奥威BI数据可视化工具凭借强大的数据处理和数据可视化能力&#xff0c;将这些维度巧妙地融合在一起&…

【Python画图-驯化01】一文叫你搭建python画图最优环境配置

【Python画图-循环01】一文叫你搭建python画图最优环境配置 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 免费获取相关内容文档关注&#…

一文get懂kwai短视频助力巴西博弈slots游戏广告优势

一文get懂kwai短视频助力巴西博弈slots游戏广告优势 在数字化时代&#xff0c;短视频广告凭借其独特的魅力和高效的传播方式&#xff0c;成为了各大品牌进行营销推广的重要手段。特别是在巴西这个充满活力的国家&#xff0c;kwai短视频广告以其独特的方式&#xff0c;为博弈游…

交友系统定制版源码| 相亲交友小程序源码全开源可二开_打造独特的社交交友系统

交友系统源码的实现涉及到多个方面&#xff0c;包括前端页面设计、后端逻辑处理、数据库设计以及用户交互等。以下是一个简单的交友系统源码实现的基本框架和关键步骤: 1.数据库设计:用户表:存储用户基本信息&#xff0c;如用户ID、用户名、密码、头像、性别、年龄、地理位置等…

探索NVIDIA A100 显卡 如何手搓A100显卡

NVIDIA A100 显卡&#xff08;GPU&#xff09;是基于NVIDIA的Ampere架构设计的高性能计算和人工智能任务的处理器。 A100显卡主要由以下几种关键芯片和组件组成&#xff1a; 1. GPU芯片 NVIDIA GA100 GPU&#xff1a; 核心组件&#xff0c;是整个显卡的核心处理单元。GA100芯…

数字IC设计-VCS和Verdi的使用

#学习记录# 前言&#xff1a;本文以一个简单的计数器来说明vcs和verdi的使用 1 代码文件 1.1 计数器代码 //Engineer&#xff1a;Mr-pn-junction module counter(input clk,input rst,output reg [5:0] count); always(posedge clk or negedge rst)beginif(!rst)coun…

【鸿蒙学习笔记】Image迭代完备

Image Image($r(app.media.zhibo)).width(96) // 图片宽度.height(96) // 图片高度.borderRadius(12) // 图片圆曲度.objectFit(ImageFit.Fill) // 不明objectFit Column({ space: 20 }) {Row() {Image($r(app.media.startIcon)).width(66).height(66).borderRadius(12)}.bac…

Qt入门小项目 | WPS tab页面(无边框窗口综合应用)

文章目录 一、手写代码实现WPS tab页面 一、手写代码实现WPS tab页面 实现类似WPS tab效果&#xff0c;具体包含&#xff1a; 自定义标题栏&#xff1a;最大、最小、关闭在QTabWidget的tab上增加控件在QTabWidget的tab上右键菜单可拖拽移动可拉伸窗口双击标题栏在最大与正常间…