flutter中常见的跨组件通讯方式

在 Flutter 开发中,事件管理和组件间通信是非常重要的。EventBus 和 NotificationListener 是两种常用的模式,它们各自有不同的使用场景和优势劣势。本文将对这两者进行比较分析,并提供代码示例。

在 Flutter 开发中,事件管理和组件间通信是非常重要的。EventBus、NotificationListener 和观察者模式是常用的三种模式,它们各自有不同的使用场景和优势劣势。本文将对这三者进行比较分析,并提供代码示例。

一、EventBus

使用场景
  1. 跨组件通信:当多个不相关的组件需要交换信息时,EventBus 非常有效。例如,在大型应用中,不同页面或模块之间的事件通知。
  2. 解耦:当希望组件之间不直接依赖于彼此,避免创建紧密耦合的关系时,EventBus 是一个很好的选择。
优势
  • 解耦:组件间的通信不需要直接引用,降低了耦合度。
  • 灵活性:可以随时添加或移除事件监听,适应性强。
  • 支持异步事件:EventBus 支持异步处理,有利于处理网络请求等耗时操作。
劣势
  • 调试困难:由于事件的流动不透明,调试时难以追踪事件来源和传递路径。
  • 可能导致内存泄漏:如果没有正确地取消订阅,可能导致内存泄漏问题。

示例代码: 

创建一个事件总线和事件类:

import 'package:event_bus/event_bus.dart';

class EventBusSingleton {
  static final EventBus _eventBus = EventBus();
  static EventBus get instance => _eventBus;
}

class MyEvent {
  final String message;
  MyEvent(this.message);
}

 然后在需要发送事件的地方发布事件:

// 发布事件
EventBusSingleton.instance.fire(MyEvent("Hello from EventBus"));

 在接受事件的组件中,订阅事件:

import 'package:flutter/material.dart';

class MyListenerWidget extends StatefulWidget {
  @override
  _MyListenerWidgetState createState() => _MyListenerWidgetState();
}

class _MyListenerWidgetState extends State<MyListenerWidget> {
  String _message = '';

  @override
  void initState() {
    super.initState();
    EventBusSingleton.instance.on<MyEvent>().listen((event) {
      setState(() {
        _message = event.message;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Text(_message);
  }
}

二、NotificationListener

使用场景
  1. 局部通知:当需要在 Widget 树中向上或向下传递通知时,NotificationListener 非常有效。例如,在列表滚动时需要通知父组件更新状态。
  2. 状态更新:在有状态的 Widget 中,可以使用 NotificationListener 来监听状态变化并进行更新。
优势
  • 简单易用:使用 NotificationListener 传递通知比较直观,尤其是在 Widget 树内。
  • 性能较高:由于 NotificationListener 是 Flutter 自身提供的机制,性能表现通常较好。
  • 支持层级结构:可以轻松地向上或向下传播通知,适合层级关系的组件。
劣势
  • 局限性:主要适用于 Widget 树内部,无法跨越 Widget 树的边界。
  • 耦合度相对较高:需要在通知的 Widget 和监听的 Widget 之间建立一定的关系。
示例代码
import 'package:flutter/material.dart';

class MyNotification extends Notification {
  final String message;
  MyNotification(this.message);
}

class NotificationSender extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () {
        MyNotification("Hello from Notification").dispatch(context);
      },
      child: Text("Send Notification"),
    );
  }
}

class NotificationReceiver extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return NotificationListener<MyNotification>(
      onNotification: (notification) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text(notification.message)),
        );
        return true; // 表示已处理
      },
      child: Column(
        children: [
          NotificationSender(),
          // 其他组件
        ],
      ),
    );
  }
}

三、观察者模式

使用场景
  1. 状态变化通知:当一个对象的状态发生变化时,多个依赖于它的对象需要得到通知。比如在数据模型变化时,更新 UI。
  2. 复杂事件系统:在一些复杂应用中,多个组件需要监听同一个事件,但又不想创建紧密耦合的关系。
优势
  • 灵活性和可扩展性:可以轻松地添加和移除观察者,而不影响其他观察者。
  • 解耦:被观察者与观察者之间不需要直接联系,降低了系统的复杂度。
劣势
  • 复杂性:实现观察者模式的代码相对复杂,尤其是在管理观察者列表时。
  • 内存管理:需要注意观察者的注册和注销,以避免内存泄漏。
示例代码
class Subject {
  final List<Observer> _observers = [];

  void attach(Observer observer) {
    _observers.add(observer);
  }

  void detach(Observer observer) {
    _observers.remove(observer);
  }

  void notify(String message) {
    for (var observer in _observers) {
      observer.update(message);
    }
  }
}

abstract class Observer {
  void update(String message);
}

class ConcreteObserver implements Observer {
  @override
  void update(String message) {
    print("Received message: $message");
  }
}

// 使用示例
void main() {
  final subject = Subject();
  final observer1 = ConcreteObserver();
  final observer2 = ConcreteObserver();

  subject.attach(observer1);
  subject.attach(observer2);

  subject.notify("Hello from Observer!");
}

四、总结

在选择 EventBus、NotificationListener 和观察者模式时,需要根据具体场景来决定:

  • EventBus:适用于跨组件、解耦需求较高的场景,尤其在大型应用中。当多个模块或页面之间需要频繁交换信息时,EventBus 是理想选择。
  • NotificationListener:适用于 Widget 树内部的局部通知,当你只需在父子组件之间传递消息时,使用 NotificationListener 更为方便高效。
  • 观察者模式:适用于需要通知多个观察者状态变化的场景,尤其是在复杂的事件系统中。它的灵活性和解耦特性使得管理复杂系统中的组件间关系更加简便。

了解它们的使用场景及优劣势,可以帮助开发者更好地管理 Flutter 应用中的事件和状态,从而提升应用的可维护性和性能。在开发过程中,根据不同的需求选择合适的模式,会使代码更清晰、更易于管理。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

为什么 ECB 模式不安全

我们先来简单了解下 ECB 模式是如何工作的 ECB 模式不涉及链接模式&#xff0c;所以也就用不着初始化向量&#xff0c;那么相同的明文分组就会被加密成相同的密文分组&#xff0c;而且每个分组运算都是独立的&#xff0c;这也就意味着可以并行提高运算效率&#xff0c;但也正是…

prometheus通过nginx-vts-exporter监控nginx

Prometheus监控nginx有两种方式。 一种是通过nginx-exporter监控&#xff0c;需要开启nginx_stub_status,主要是nginx自身的status信息&#xff0c;metrics数据相对较少&#xff1b; 另一种是使用nginx-vts-exporter监控&#xff0c;但是需要在编译nginx的时候添加nginx-module…

Shader 中的光源

1、Shader 开发中常用的光源属性 Unity当中一共支持四种光源类型&#xff1a; 平行光&#xff08;Directional&#xff09;点光源&#xff08;Point&#xff09;聚光灯&#xff08;Spot&#xff09;面光源&#xff08;Area&#xff09;— 面光源仅在烘焙时有用 不管光源类型到…

Docker 华为云镜像加速器配置

​​ 操作说明 1. 安装/升级容器引擎客户端 推荐安装1.11.2以上版本的容器引擎客户端 2. 加速器地址 访问华为云容器镜像服务&#xff1a;https://console.huaweicloud.com/swr/ 获取加速器地址 https://xxxxxxxxx.mirror.swr.myhuaweicloud.com3. 配置镜像加速器 针对…

【Qt | QLineEdit】Qt 中使 QLineEdit 响应 鼠标单击、双击事件 的两个方法

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; ⏰发布时间⏰&#xff1a; 2024-09-14 …

Flutter-底部选择弹窗(showModalBottomSheet)

前言 现在有个需求&#xff0c;需要用底部弹窗来添加定时的重复。在这里使用原生的showModalBottomSheet来实现 showModalBottomSheet的Props 名称 描述 isScrollControlled全屏还是半屏isDismissible外部是否可以点击&#xff0c;false不可以点击&#xff0c;true可以点击&a…

STM32 移植FATFS时遇到ff_oem2uni函数未定义问题

STM32 移植FATFS时遇到ff_oem2uni/ff_uni2oem/ff_wtoupper函数未定义问题 在移植STM32 FATFS文件系统代码时&#xff0c;完成后编译遇到如下错误&#xff1a; 经过排查分析&#xff0c;是文件没有添加完全导致的&#xff1a; 把ffunicode.c文件添加进工程就可以了&#xff…

01-Mac OS系统如何下载安装Python解释器

目录 Mac安装Python的教程 mac下载并安装python解释器 如何下载和安装最新的python解释器 访问python.org&#xff08;受国内网速的影响&#xff0c;访问速度会比较慢&#xff0c;不过也可以去我博客的资源下载&#xff09; 打开历史发布版本页面 进入下载页 鼠标拖到页面…

MongoDB解说

MongoDB 是一个流行的开源 NoSQL 数据库&#xff0c;它使用了一种被称为文档存储的数据库模型。 与传统的关系型数据库管理系统&#xff08;RDBMS&#xff09;不同&#xff0c;MongoDB 不使用表格来存储数据&#xff0c;而是使用了一种更为灵活的格式——JSON 样式的文档。 这…

论文阅读笔记:Sapiens: Foundation for Human Vision Models

Sapiens: Foundation for Human Vision Models 1 背景1.1 问题1.2 目标 2 方法3 创新点4 模块4.1 Humans-300M数据集4.2 预训练4.3 2D位姿估计4.4 身体部位分割4.5 深度估计4.6 表面法线估计 5 实验5.1 实现细节5.2 2D位姿估计5.3 身体部位分割5.4 深度估计5.5 表面法线估计5.6…

SVN笔记-SVN安装

SVN笔记-SVN安装 1、在windows下安装 SVN 1、准备svn的安装文件 下载地址&#xff1a;https://sourceforge.net/projects/win32svn/ 2、下载完成后&#xff0c;在相应的盘符中会有一个Setup-Subversion-1.8.17.msi的文件&#xff0c;目前最新的版本是1.8.17&#xff0c; 这里…

UGit:腾讯自研的Git客户端新宠

UGit 是一款专门针对腾讯内部研发环境特点量身定制的 Git 客户端&#xff0c;其目标在于大幅提升开发效率以及确保团队协作的高度流畅性。UGit 能够良好地支持 macOS 10.11 及以上版本、Apple Silicon 以及 Win64 位系统。 可以下载体验一把。 https://ugit.qq.com/zh/index.…

【CSS Tricks】如何做一个粒子效果的logo

效果展示 代码展示 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>粒子效果Logo</title>…

【图像匹配】基于Harris算法的图像匹配,matlab实现

博主简介&#xff1a;matlab图像代码项目合作&#xff08;扣扣&#xff1a;3249726188&#xff09; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本次案例是基于基于Harris算法的图像匹配&#xff0c;用matlab实现。 一、案例背景和算法介绍 …

echarts 散点图tooltip显示一个点对应多个y值

tooltip&#xff1a;显示 tooltip: {trigger: "axis",extraCssText: max-width:50px; white-space:pre-wrap,formatter: function (params) {let arr []params.forEach(v > {arr.push(v.data[1])});return params[0].data[0]":<br>["arr.toStr…

Android 签名、空包签名 、jarsigner、apksigner

jarsigner是JDK提供的针对jar包签名的通用工具, 位于JDK/bin/jarsigner.exe apksigner是Google官方提供的针对Android apk签名及验证的专用工具, 位于Android SDK/build-tools/SDK版本/apksigner.bat jarsigner&#xff1a; jarsigner签名空包执行的命令&#xff1a; jar…

解决Hive乱码问题

在插入数据后&#xff0c;发现hive乱码 原因&#xff1a;Hive默认将存储表结构的元数据列编码设置为latin1&#xff0c;不支持中文 解决方法&#xff1a;在MySQL中修改对应Hive元数据列的编码 先查看mysql的所有字符集编码 1、先修改my.cnf 代码如下&#xff1a; vim /etc/…

weblogic CVE-2017-3506 靶场攻略

漏洞描述 Weblogic的WLS Security组件对外提供了webserver服务&#xff0c;其中使⽤了XMLDecoder来解析⽤户输⼊的XML数据&#xff0c;在解析过程中出现反序列化漏洞&#xff0c;可导致任意命令执⾏。 影响版本 受影响版本&#xff1a;WebLogic 10.3.6.0, 12.1.3.0, 12.2.1.…

YOLOv8改进 | 自定义数据集训练 | AirNet助力YOLOv8检测

目录 一、本文介绍 二、AirNet原理介绍 2.1 对比基降解编码器&#xff08;CBDE&#xff09; 2.2 降解引导修复网络&#xff08;DGRN&#xff09; 三、yolov8与AirNet结合修改教程 3.1 核心代码文件的创建与添加 3.1.1 AirNet.py文件添加 3.1.2 __init__.py文件添加 3…

AIGC时代!AI的“iPhone时刻”与投资机遇

AIGC时代&#xff01;AI的“iPhone时刻”与投资机遇 前言AI的“iPhone时刻”与投资机遇 前言 AIGC&#xff0c;也就是人工智能生成内容&#xff0c;它就像是一股汹涌的浪潮&#xff0c;席卷了整个科技世界。它的出现&#xff0c;让我们看到了人工智能的无限潜力&#xff0c;也…