当前位置: 首页 > article >正文

(二十六)Java观察者模式在Android开发中的应用详解

Java观察者模式在Android开发中的应用

观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,使得多个观察者对象可以同时监听一个主题对象。当主题对象的状态发生变化时,所有注册的观察者都会收到通知并自动更新自己。在Android开发中,观察者模式被广泛应用于UI事件处理、数据绑定、消息传递等场景。本文将详细讲解观察者模式在Android中的具体应用,并结合代码示例和使用场景进行说明。


观察者模式的基本结构

观察者模式通常包含以下几个核心角色:

  1. 主题(Subject)
    • 被观察的对象,负责维护一个观察者列表,并提供方法来注册、注销观察者以及通知观察者。
  2. 观察者(Observer)
    • 监听主题对象状态变化的接口或类,定义了状态变化时需要执行的操作。
  3. 具体主题(Concrete Subject)
    • 主题的具体实现,维护状态并在状态变化时通知所有观察者。
  4. 具体观察者(Concrete Observer)
    • 观察者的具体实现,定义收到通知后的具体行为。

观察者模式的核心思想是解耦主题和观察者,使得两者可以独立变化,同时保持松散耦合的关系。


Android中观察者模式的应用场景

在Android开发中,观察者模式被广泛应用于各种框架和组件中,以下是几个典型的使用场景及其代码示例。

1. UI组件的事件监听

Android的UI组件(如ButtonTextView等)通常通过事件监听机制实现用户交互,这种机制本质上就是观察者模式的应用。UI组件作为主题,监听器作为观察者。

示例代码

以下是一个Button点击事件的监听示例:

Button button = findViewById(R.id.my_button);
button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(MainActivity.this, "Button clicked!", Toast.LENGTH_SHORT).show();}
});
场景分析
  • 主题Button对象。
  • 观察者OnClickListener接口的匿名实现。
  • 工作原理:当用户点击Button时(状态变化),Button会调用注册的OnClickListeneronClick方法,通知观察者执行相应操作。

这种方式广泛用于处理用户输入,例如点击、长按、滑动等事件。


2. BroadcastReceiver(广播接收器)

Android中的BroadcastReceiver用于接收系统或应用发送的广播消息,其设计也遵循观察者模式。广播发送者是主题,BroadcastReceiver是观察者。

示例代码

以下是一个监听设备启动完成广播的示例:

// 定义广播接收器
public class BootReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Toast.makeText(context, "Device booted!", Toast.LENGTH_SHORT).show();}
}// 在Activity中注册广播接收器
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);IntentFilter filter = new IntentFilter("android.intent.action.BOOT_COMPLETED");registerReceiver(new BootReceiver(), filter);}
}
场景分析
  • 主题:发送广播的系统或组件(例如系统启动时发送BOOT_COMPLETED)。
  • 观察者BootReceiver实例。
  • 工作原理:当系统发出广播时,所有注册的相关BroadcastReceiver都会收到通知并执行onReceive方法。

这种机制适用于跨组件通信,例如监听电池电量变化、网络状态变化等。


3. LiveData(数据绑定)

LiveData是Android Jetpack提供的一个可观察的数据持有者,广泛用于MVVM架构中。它遵循观察者模式,允许UI组件观察数据的变化并自动更新。

示例代码

以下是一个使用LiveData的简单示例:

// 定义ViewModel
public class MyViewModel extends ViewModel {private MutableLiveData<String> data = new MutableLiveData<>();public LiveData<String> getData() {return data;}public void setData(String newData) {data.setValue(newData);}
}// 在Activity中观察LiveData
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class);TextView textView = findViewById(R.id.text_view);// 注册观察者viewModel.getData().observe(this, new Observer<String>() {@Overridepublic void onChanged(String s) {textView.setText(s); // 更新UI}});// 模拟数据变化findViewById(R.id.update_button).setOnClickListener(v -> viewModel.setData("New Data"));}
}
场景分析
  • 主题LiveData对象。
  • 观察者Observer接口的实现。
  • 工作原理:当LiveData的数据通过setValuepostValue改变时,所有活跃的观察者(如Activity或Fragment)都会收到通知并执行onChanged方法。

LiveData特别适合需要在数据变化时自动更新UI的场景,且它支持生命周期感知,避免内存泄漏。


4. RxJava(异步事件流处理)

RxJava是一个基于观察者模式的库,用于处理异步操作和事件流。Observable作为主题,Observer作为观察者。

示例代码

以下是一个简单的RxJava示例:

Observable.just("Hello", "World").subscribeOn(Schedulers.io()) // 在IO线程执行.observeOn(AndroidSchedulers.mainThread()) // 在主线程观察.subscribe(new Observer<String>() {@Overridepublic void onSubscribe(Disposable d) {// 订阅开始}@Overridepublic void onNext(String s) {Log.d("RxJava", "Received: " + s); // 处理数据}@Overridepublic void onError(Throwable e) {Log.e("RxJava", "Error: " + e.getMessage());}@Overridepublic void onComplete() {Log.d("RxJava", "Completed");}});
场景分析
  • 主题Observable对象。
  • 观察者Observer接口的实现。
  • 工作原理Observable发出数据流,Observer订阅后接收数据并执行onNext方法,直到完成(onComplete)或出错(onError)。

RxJava适用于复杂的异步任务处理,例如网络请求、数据库操作等。


自定义观察者模式实现

除了使用Android提供的组件和库,开发者也可以根据需求自定义观察者模式。以下是一个简单的自定义实现。

示例代码

// 主题接口
public interface Subject {void registerObserver(Observer o);void removeObserver(Observer o);void notifyObservers();
}// 观察者接口
public interface Observer {void update(String message);
}// 具体主题
public class ConcreteSubject implements Subject {private List<Observer> observers = new ArrayList<>();private String message;@Overridepublic void registerObserver(Observer o) {observers.add(o);}@Overridepublic void removeObserver(Observer o) {observers.remove(o);}@Overridepublic void notifyObservers() {for (Observer o : observers) {o.update(message);}}public void setMessage(String message) {this.message = message;notifyObservers();}
}// 具体观察者
public class ConcreteObserver implements Observer {private String name;public ConcreteObserver(String name) {this.name = name;}@Overridepublic void update(String message) {Log.d("Observer", name + " received message: " + message);}
}// 使用示例
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ConcreteSubject subject = new ConcreteSubject();Observer observer1 = new ConcreteObserver("Observer1");Observer observer2 = new ConcreteObserver("Observer2");subject.registerObserver(observer1);subject.registerObserver(observer2);subject.setMessage("Hello, Observers!");}
}
运行结果

当调用setMessage("Hello, Observers!")时,日志输出:

Observer1 received message: Hello, Observers!
Observer2 received message: Hello, Observers!
场景分析
  • 主题ConcreteSubject,维护消息状态并通知观察者。
  • 观察者ConcreteObserver,接收消息并打印。
  • 适用场景:适用于需要自定义通知机制的场景,例如应用内的消息分发系统。

总结

观察者模式在Android开发中应用广泛,从UI事件监听(如OnClickListener)、广播接收(BroadcastReceiver)、数据绑定(LiveData),到异步处理(RxJava),都体现了其灵活性和解耦性。通过理解观察者模式的核心思想,开发者可以更好地设计Android应用的功能模块,提升代码的可维护性和扩展性。无论是使用系统提供的工具还是自定义实现,观察者模式都是Android开发中不可或缺的设计模式之一。

相关文章:

(二十六)Java观察者模式在Android开发中的应用详解

Java观察者模式在Android开发中的应用 观察者模式&#xff08;Observer Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一种一对多的依赖关系&#xff0c;使得多个观察者对象可以同时监听一个主题对象。当主题对象的状态发生变化时&#xff0c;所有注册的观察者…...

【SpringMVC】深入解析自定义拦截器、注册配置拦截器、拦截路径方法及常见拦截路径、排除拦截路径、拦截器的执行流程

拦截器 上个章节我们完成了强制登录的功能, 后端程序根据Session来判断用户是否登录, 但是实现方法是比较麻烦的&#xff1a; 需要修改每个接口的处理逻辑需要修改每个接口的返回结果接口定义修改, 前端代码也需要跟着修改 有没有更简单的办法, 统一拦截所有的请求, 并进行Se…...

基于VS Code 为核心平台的python语言智能体开发平台搭建

以下是基于 VS Code 为核心平台&#xff0c;整合 Node-RED、Gradio、Docker Desktop 的智能体可视化开发平台优化方案&#xff0c;聚焦工具链深度集成与开发效率提升&#xff1a; 一、核心架构设计 #mermaid-svg-f8l9kYPAlJ2TlpGF {font-family:"trebuchet ms",verd…...

使用最新threejs复刻经典贪吃蛇游戏的3D版,附完整源码

基类Entity 建立基类Entity&#xff0c;实现投影能力、动画入场效果&#xff08;从小变大的弹性动画&#xff09;、计算自己在地图格位置的方法。 // 导入gsap动画库&#xff08;用于创建补间动画&#xff09; import gsap from gsap// 定义Entity基类 export default class …...

论坛测试报告

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…...

IPMI 与 Redfish API简介

--- ### **IPMI 与 Redfish API 详解** #### **1. IPMI(智能平台管理接口)** **简介** IPMI(Intelligent Platform Management Interface)是一种硬件级别的带外管理标准,允许管理员通过独立于操作系统的网络通道(BMC)监控和管理服务器硬件,即使主机已关机或操作系…...

zset.

zset 有序集合 zset 保留了 set 不能有重复元素的特点 zset 中的每个元素都有一个唯一的浮点类型的分数&#xff08;score&#xff09;与之关联&#xff0c;使得 zset 内部的元素是可以维护有序性的。但是这个有序不是用下标作为排序依据的&#xff0c;而是根据分数&#xf…...

Windows 部署 DeepSeek 详细教程

一、准备工作 系统要求&#xff1a; 建议Windows 10 22H2 或更高版本&#xff0c;家庭版或专业版上网环境&#xff1a; 建议科学上网&#xff0c;国内访问部分网站会很慢设备要求&#xff1a; 内存8G以上、关闭防火墙 二、安装Ollama 官网链接: https://ollama.com/downloadg…...

过去十年前端框架演变与技术驱动因素剖析

一、技术演进脉络&#xff08;2013-2023&#xff09; 2013-2015&#xff1a;结构化需求催生框架雏形 早期的jQuery虽然解决了跨浏览器兼容性问题&#xff08;如IE8兼容性处理&#xff09;&#xff0c;但其松散的代码组织方式难以支撑复杂应用开发。Backbone.js的出现首次引入M…...

从零开始学A2A一:A2A 协议的高级应用与优化

A2A 协议的高级应用与优化 学习目标 掌握 A2A 高级功能 理解多用户支持机制掌握长期任务管理方法学习服务性能优化技巧 理解与 MCP 的差异 分析多智能体场景下的优势掌握不同场景的选择策略 第一部分&#xff1a;多用户支持机制 1. 用户隔离架构 #mermaid-svg-Awx5UVYtqOF…...

#Linux动态大小裁剪以及包大小变大排查思路

1 动态库裁剪 库分为动态库和静态库&#xff0c;动态库是在程序运行时才加载&#xff0c;静态库是在编译时就加载到程序中。动态库的大小通常比静态库小&#xff0c;因为动态库只包含了程序需要的函数和数据&#xff0c;而静态库则包含了所有的函数和数据。静态库可以理解为引入…...

基于微信小程序的中医小妙招系统的设计与实现

hello hello~ &#xff0c;这里是 code袁~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生…...

sqlite3的API以及命令行

sqlite是目前最流行的嵌入式数据库。 所谓嵌入式&#xff0c;就是足够简单&#xff0c;可以嵌入到我们自己开发的应用程序之中。 在Linux系统中&#xff0c;sqlite的使用只需要使用它的API&#xff0c;连接它的动态连接库&#xff0c;甚至都不用连接&#xff0c;sqlite的实现…...

css button 点击效果

<!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><title>button点击效果</title><style>#container {display: flex;align-items: center;justify-content: center;}.pushable {position: relat…...

表征流体作用力的参数及其特性

在圆柱绕流研究中&#xff0c;这些参数分别表征流体作用力的关键特性&#xff0c;以下是详细解析&#xff1a; &#x1f4ca; 参数物理意义及工程应用 符号名称物理意义典型值范围&#xff08;参考&#xff09;工程意义 C d m a x C_{dmax} Cdmax​最大阻力系数瞬时阻力系数&a…...

Foundation Agent:深度赋能AI4DATA

2025年5月17日&#xff0c;第76期DataFunSummit&#xff1a;AI Agent技术与应用峰会将在DataFun线上社区举办。Manus的爆火并非偶然&#xff0c;随着基础模型效果不断的提升&#xff0c;Agent作为大模型的超级应用备受全世界的关注。为了推动其技术和应用&#xff0c;本次峰会计…...

Docker--Docker镜像原理

docker 是操作系统层的虚拟化&#xff0c;所以 docker 镜像的本质是在模拟操作系统。 联合文件系统&#xff08;UnionFS&#xff09; 联合文件系统&#xff08;UnionFS&#xff09; 是Docker镜像实现分层存储的核心技术&#xff0c;它通过将多个只读层&#xff08;Image Laye…...

SpringAI+DeepSeek大模型应用开发——2 大模型应用开发架构

目录 2.大模型开发 2.1 模型部署 2.1.1 云服务-开放大模型API 2.1.2 本地部署 搜索模型 运行大模型 2.2 调用大模型 接口说明 提示词角色 ​编辑 会话记忆问题 2.3 大模型应用开发架构 2.3.1 技术架构 纯Prompt模式 FunctionCalling RAG检索增强 Fine-tuning …...

Transformer 架构 - 编码器 (Transformer Architecture - Encoder)

1.Transformer 编码器整体结构 Transformer 编码器的结构相对直观:它由 N 个完全相同的编码器层 (Encoder Layer) 堆叠而成。 图1: Transformer 编码器整体结构示意图 (简化) 输入序列(例如,通过 embedding 层转换后的词向量)首先会加上位置编码,然后传入第一个编码器层…...

2.2/Q2,Charls最新文章解读

文章题目&#xff1a;Association of uric acid to high-density lipoprotein cholesterol ratio with the presence or absence of hypertensive kidney function: results from the China Health and Retirement Longitudinal Study (CHARLS) DOI&#xff1a;10.1186/s12882-…...

下拉框select标签类型

在我们很多页面里有下拉框的选择&#xff0c;这种元素怎么定位呢&#xff1f;下拉框分为两种类型&#xff1a;我们分别针对这两种元素进行定位和操作 select标签 &#xff1a; 通过select类处理。 非select标签 1、针对下拉框元素&#xff0c;如果是Select标签类型&#xff0c;…...

CentOS 7 linux系统从无到有部署项目

环境部署操作手册 一、Maven安装与配置 1. 下载与解压 下载地址&#xff1a;https://maven.apache.org/download.cgi?spm5238cd80.38b417da.0.0.d54c32cbnOpQh2&filedownload.cgi上传并解压解压命令&#xff1a; tar -zxvf apache-maven-3.9.9-bin.tar.gz -C /usr/loc…...

李飞飞团队新作WorldScore:“世界生成”能力迎来统一评测,3D/4D/视频模型同台PK

从古老神话中对世界起源的幻想&#xff0c;到如今科学家们在实验室里对虚拟世界的构建&#xff0c;人类探索世界生成奥秘的脚步从未停歇。如今&#xff0c;随着人工智能和计算机图形学的深度融合&#xff0c;我们已站在一个全新的起点&#xff0c;能够以前所未有的精度和效率去…...

如何在米尔-STM32MP257开发板上部署环境监测系统

本文将介绍基于米尔电子MYD-LD25X开发板&#xff08;米尔基于STM35MP257开发板&#xff09;的环境监测系统方案测试。 摘自优秀创作者-lugl4313820 一、前言 环境监测是当前很多场景需要的项目&#xff0c;刚好我正在论坛参与的一个项目&#xff1a;Thingy:91X 蜂窝物联网原型…...

MySQL之SQL优化

目录 1.插入数据 2.大批量插入数据 3.order by优化 4.group by优化 5.limit优化 6.count优化 count用法 7.update优化 1.插入数据 如果我们需要一次性往数据库表中插入多条记录&#xff0c;可以从以下三个方面进行优化 第一个:批量插入数据 Insert into tb_test va…...

python_level1.2

目录 一、变量 例如&#xff1a;小正方形——>大正方形 【1】第一次使用这个变量&#xff0c;所以说&#xff1a;定义一个变量length&#xff1b; 【2】&#xff1a;是赋值符号&#xff0c;不是等于符号。&#xff08;只有赋值&#xff0c;该变量才会被创建&#xff09;…...

Linux、Kylin OS挂载磁盘,开机自动加载

0.实验环境&#xff1a; 1.确定挂载目录&#xff0c;如果没有使用mkdir 进行创建&#xff1a; mkdir /data 2.查看磁盘 lsblk #列出所有可用的块设备df -T #查看磁盘文件系统类型 3.格式化成xfs文件系统 (这里以xfs为例&#xff0c;ext4类似) mkfs.xfs /dev/vdb 4.挂载到…...

FPGA-VGA

目录 前言 一、VGA是什么&#xff1f; 二、物理接口 三、VGA显示原理 四、VGA时序标准 五、VGA显示参数 六、模块设计 七、波形图设计 八、彩条波形数据 前言 VGA的FPGA驱动 一、VGA是什么&#xff1f; VGA&#xff08;Video Graphics Array&#xff09;是IBM于1987年推出的…...

java的lambda和stream流操作

Lambda 表达式 ≈ 匿名函数 &#xff08;Lambda接口&#xff09;函数式接口&#xff1a;传入Lambda表达作为函数式接口的参数 函数式接口 只能有一个抽象方法的接口 Lambda 表达式必须赋值给一个函数式接口&#xff0c;比如 Java 8 自带的&#xff1a; 接口名 作用 Functio…...

【嵌入式】【阿里云服务器】【树莓派】学习守护进程编程、gdb调试原理和内网穿透信息

目录 一. 守护进程的含义及编程实现的主要过程 1.1守护进程 1.2编程实现的主要过程 二、在树莓派中通过三种方式创建守护进程 2.1nohup命令创建 2.2fork()函数创建 2.3daemon()函数创建 三、在阿里云中通过三种方式创建守护进程 3.1nohup命令创建 3.2fork()函数创建 …...