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

Flutter 中的数据跨层传递方案

在 Flutter 中,数据跨层传递(从父组件向子组件传递数据,或从子组件向父组件传递)有多种方案,主要包括以下几种:


1. 直接参数传递(Constructor 参数)

适用场景

  • 父组件向子组件传递数据,适用于层级关系较浅的情况。

示例

class ParentWidget extends StatelessWidget {final String message = "Hello from Parent";Widget build(BuildContext context) {return ChildWidget(message: message);}
}class ChildWidget extends StatelessWidget {final String message;const ChildWidget({required this.message});Widget build(BuildContext context) {return Text(message);}
}

优点:简单、直观。
缺点:如果层级较深,可能需要逐层传递,导致“参数传递链”问题。


2. InheritedWidget(Flutter 低级状态管理方案)

适用场景

  • 子 Widget 跨层共享父 Widget 的属性,且数据不会频繁更新。

示例

class MyDataProvider extends InheritedWidget {final String data;const MyDataProvider({required this.data, required Widget child}) : super(child: child);static MyDataProvider? of(BuildContext context) {return context.dependOnInheritedWidgetOfExactType<MyDataProvider>();}bool updateShouldNotify(covariant MyDataProvider oldWidget) {return oldWidget.data != data;}
}class ParentWidget extends StatelessWidget {Widget build(BuildContext context) {return MyDataProvider(data: "Hello from InheritedWidget",child: ChildWidget(),);}
}class ChildWidget extends StatelessWidget {Widget build(BuildContext context) {final provider = MyDataProvider.of(context);return Text(provider?.data ?? "No data");}
}

优点:数据可在组件树中被多个组件访问,无需手动传递。
缺点:手写较繁琐,通常与 ChangeNotifierProvider 结合使用。


3. Provider(推荐)

适用场景

  • 全局状态管理,适用于多个页面共享数据的情况。

示例

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';class CounterProvider with ChangeNotifier {int count = 0;void increment() {count++;notifyListeners();}
}void main() {runApp(ChangeNotifierProvider(create: (_) => CounterProvider(),child: MyApp(),),);
}class MyApp extends StatelessWidget {Widget build(BuildContext context) {return MaterialApp(home: CounterPage(),);}
}class CounterPage extends StatelessWidget {Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("Provider Example")),body: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Text("Count: ${context.watch<CounterProvider>().count}"),ElevatedButton(onPressed: () {context.read<CounterProvider>().increment();},child: Text("Increment"),),],),);}
}

优点:官方推荐、简洁、支持自动通知 UI 更新。
缺点:需要引入 provider 包。


4. Riverpod(增强版 Provider)

适用场景

  • 需要更强的依赖注入和状态管理能力,避免 Provider 的嵌套问题。

示例

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';final counterProvider = StateProvider<int>((ref) => 0);void main() {runApp(ProviderScope(child: MyApp()));
}class MyApp extends StatelessWidget {Widget build(BuildContext context) {return MaterialApp(home: CounterPage(),);}
}class CounterPage extends ConsumerWidget {Widget build(BuildContext context, WidgetRef ref) {final count = ref.watch(counterProvider);return Scaffold(appBar: AppBar(title: Text("Riverpod Example")),body: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Text("Count: $count"),ElevatedButton(onPressed: () => ref.read(counterProvider.notifier).state++,child: Text("Increment"),),],),);}
}

优点:比 Provider 更简洁、更强大,避免 context 依赖问题。
缺点:学习成本较高,需要使用 flutter_riverpod 包。


5. GetX(轻量级但强大的状态管理)

适用场景

  • 想要减少模板代码,并需要更高性能的状态管理。

示例

import 'package:flutter/material.dart';
import 'package:get/get.dart';class CounterController extends GetxController {var count = 0.obs;void increment() => count++;
}void main() {runApp(GetMaterialApp(home: CounterPage()));
}class CounterPage extends StatelessWidget {final CounterController controller = Get.put(CounterController());Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("GetX Example")),body: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Obx(() => Text("Count: ${controller.count}")),ElevatedButton(onPressed: controller.increment,child: Text("Increment"),),],),);}
}

优点:无需 context,代码简洁,性能高。
缺点:非官方方案,项目可能不易维护。


6. EventBus(跨组件间事件通信)

适用场景

  • 非父子组件之间传递数据,比如 多个页面或多个独立的组件 之间通信。

示例

import 'package:event_bus/event_bus.dart';final EventBus eventBus = EventBus();class DataEvent {final String data;DataEvent(this.data);
}// 发送事件
eventBus.fire(DataEvent("Hello EventBus"));// 监听事件
eventBus.on<DataEvent>().listen((event) {print(event.data);
});

优点:适合全局事件通信,避免组件嵌套传参。
缺点:管理不当可能导致事件滥用,影响代码可读性。


7. Notification(从子组件向父组件传递数据)

适用场景

  • 适用于 子组件向父组件发送事件通知,常用于 滚动监听交互事件 等情况。

示例

子组件 发送 CustomNotification,父组件 监听 并接收通知:

import 'package:flutter/material.dart';// 自定义通知类
class CustomNotification extends Notification {final String message;CustomNotification(this.message);
}class NotificationExample extends StatelessWidget {Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("Notification Example")),body: NotificationListener<CustomNotification>(onNotification: (notification) {ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("收到通知: ${notification.message}")),);return true; // 返回 true,表示已处理通知},child: ChildWidget(),),);}
}class ChildWidget extends StatelessWidget {Widget build(BuildContext context) {return Center(child: ElevatedButton(onPressed: () {CustomNotification("Hello, Parent!").dispatch(context);},child: Text("发送通知"),),);}
}void main() {runApp(MaterialApp(home: NotificationExample()));
}

解析

  • NotificationListener<CustomNotification> 监听 子组件 ChildWidget 发送的 CustomNotification 事件。
  • CustomNotification("Hello, Parent!").dispatch(context); 从子组件向上传递通知,并触发 onNotification 方法。
  • ScaffoldMessenger.of(context).showSnackBar(...) 在父组件显示通知

优点

  • 适合 从子组件向上 传递事件,而无需父组件主动监听或传递回调函数。
  • 无需 Provider、全局状态,适用于简单的事件通知。

缺点

  • 不适合传递复杂数据(比如全局状态)。
  • 仅能向上级组件传递,不能横向或全局广播数据。

使用场景

  • 子组件通知父组件某些事件发生(如按钮点击、用户输入变化)。
  • 监听滚动事件ScrollNotification)。
  • 监听输入框变化FormField 自带 FormFieldState)。

总结

方案方向适用场景优点缺点
构造函数传参父 → 子普通数据传递简单直观层级深时麻烦
InheritedWidget父 → 子共享数据但不频繁变更内置方案代码较复杂
Provider全局官方推荐,适合全局状态易用高效需要第三方库
Riverpod全局更强大的依赖管理简单、无 context 限制学习成本
GetX全局轻量级状态管理代码简洁,性能好非官方方案
EventBus任意跨组件通信适合全局事件可能滥用
Notification子 → 父子组件通知父组件无需回调,适合单向事件仅支持向上传递

结论

  • 状态管理:推荐 Provider / Riverpod
  • 子 → 父传递Notification(事件通知),或者直接 回调Function)。
  • 轻量级方案GetX(简洁),或者 直接 StatefulWidget 维护本地状态。

相关文章:

Flutter 中的数据跨层传递方案

在 Flutter 中&#xff0c;数据跨层传递&#xff08;从父组件向子组件传递数据&#xff0c;或从子组件向父组件传递&#xff09;有多种方案&#xff0c;主要包括以下几种&#xff1a; 1. 直接参数传递&#xff08;Constructor 参数&#xff09; 适用场景&#xff1a; 父组件向…...

代码随想录D50-51 图论 Python

理论基础 理论基础部分依然沿用代码随想录教程中的介绍&#xff1a; 图的种类 度 连通性 连通性用于表示图中节点的连通情况。 如果有节点不能到达其他节点&#xff0c;则为非连通图&#xff0c;想象将多个水分子表示为图&#xff0c;不考虑非键作用&#xff0c;这张图就不是…...

MyBatis进阶

日志的使用 我们在使用MyBatis的时候, 其实MyBatis框架会打印一些必要的日志信息, 在开发阶段这些日志信息对我们分析问题,理解代码的执行是特别有帮助的; 包括项目上线之后,我们也可以收集项目的错误日志到文件里面去; 所以我们采用专门的日志系统来处理. 步骤 导入坐标拷贝…...

容器化部署Kafka的最佳实践:基于KRaft模式的无ZooKeeper方案

一、docker 部署kafka单节点 1.1安装docker 可以参考这篇CentOS 7安装docker并配置镜像加速 1.3 运行kafka&#xff08;注意修改zookeeper&#xff0c;kafka地址&#xff09; docker run -d --name kafka -e KAFKA_ADVERTISED_LISTENERSPLAINTEXT://172.16.10.180:9092 -p …...

DeepSeek核心算法解析:如何打造比肩ChatGPT的国产大模型

注&#xff1a;此文章内容均节选自充电了么创始人&#xff0c;CEO兼CTO陈敬雷老师的新书《自然语言处理原理与实战》&#xff08;人工智能科学与技术丛书&#xff09;【陈敬雷编著】【清华大学出版社】 文章目录 DeepSeek大模型技术系列一DeepSeek核心算法解析&#xff1a;如何…...

LeetCode-633. 平方数之和

1、题目描述 给定一个非负整数 c &#xff0c;你要判断是否存在两个整数 a 和 b&#xff0c;使得 a2 b2 c 。 示例 1&#xff1a; 输入&#xff1a;c 5 输出&#xff1a;true 解释&#xff1a;1 * 1 2 * 2 5示例 2&#xff1a; 输入&#xff1a;c 3 输出&#xff1a;f…...

前端面试技巧与实践

在当今快速发展的互联网行业中&#xff0c;前端开发已经成为了一个至关重要的角色。随着技术的不断进步和用户需求的日益复杂&#xff0c;前端工程师的职责不再仅仅是实现页面的布局和交互&#xff0c;而是需要具备全方位的技术能力和工程思维。根据2023年Stack Overflow的开发…...

windows Redis Insight 如何查看宝塔docker里的redis数据

1、ping 命令用于测试网络连通性&#xff0c;它只需要目标 IP 地址作为参数&#xff0c;不需要端口号。正确的命令如下&#xff1a; ping 公网地址2、使用 Telnet 测试端口连通性 telnet 公网地址 端口 telnet 47.108.67.228 6379如果连接成功&#xff0c;窗口会变为空白&am…...

sql数据执行失败,三个命令依次执行

set global innodb_strict_mode off set global.sql_mode ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION; set sql_mode ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION;...

BGP配置华为——RR反射器配置

实验拓扑 与之前实验同理将loop0作为routerID使用&#xff0c;且R1和R2上用loop1接口用于模拟用户其他网段 实验要求 1&#xff0c;在AS100内运行OSPF协议 2.配置路由反射器&#xff0c;使得从R1进入的数据能够反射到全局网络 3.在R1和R2上分别宣告自己的loop1口网段用于观…...

基于Flask的艺恩影片票房分析系统的设计与实现

【Flask】基于Flask的艺恩影片票房分析系统的设计与实现&#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 该系统利用Python编程语言进行后端开发&#xff0c;结合Echarts进行数据的可视化展示&a…...

架构设计系列(三):架构模式

一、概述 关于移动应用开发中常见的架构模式&#xff0c;这些模式是为了克服早期模式的局限性而引入。常见的 架构模式有&#xff1a; MVC, MVP, MVVM, MVVM-C, and VIPER 二、MVC, MVP, MVVM, MVVM-C, and VIPER架构模式 MVC、MVP、MVVM、MVVM-C 和 VIPER 是移动应用开发中…...

零基础学QT、C++(一)安装QT

目录 如何快速学习QT、C呢&#xff1f; 一、编译器、项目构建工具 1、编译器&#xff08;介绍2款&#xff09; 2、项目构建工具 二、安装QT 1、下载QT安装包 2、运行安装包 3、运行QT creator 4、导入开源项目 总结 闲谈 如何快速学习QT、C呢&#xff1f; 那就是项目驱动法&…...

SQL注入(SQL Injection)详解与实战

文章目录 一、什么是SQL注入&#xff1f;二、常见SQL注入类型三、手动注入步骤&#xff08;以CTF题目为例&#xff09;四、CTF实战技巧五、自动化工具&#xff1a;SQLMap六、防御措施七、CTF例题八、资源推荐 一、什么是SQL注入&#xff1f; SQL注入是一种通过用户输入构造恶意…...

【Prometheus】prometheus结合domain_exporter实现域名监控

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…...

Java 设计模式之命令模式

文章目录 Java 设计模式之命令模式概述UML代码实现简单实现复杂实现 Java 设计模式之命令模式 概述 命令模式(Command)&#xff1a;将一个请求封装为一个对象&#xff0c;从而使你可用不同的请求对客户进行参数化&#xff1b;对请求排队或记录请求日志&#xff0c;以及支持可…...

BT401双模音频蓝牙模块如何开启ble的透传,有什么注意事项

BT401音频蓝牙模块如何开启ble的透传&#xff1f; 首先BT401的蓝牙音频模块&#xff0c;分为两个版本&#xff0c;dac版本和iis数字音频版本 DAC版本&#xff1a;就是BT401蓝牙模块【9和10脚】直接输出模拟音频信号&#xff0c;也就是说&#xff0c;直接推动耳机可以听到声音 …...

利用二分法+布尔盲注、时间盲注进行sql注入

一、布尔盲注&#xff1a; import requestsdef binary_search_character(url, query, index, low32, high127):while low < high:mid (low high 1) // 2payload f"1 AND ASCII(SUBSTRING(({query}),{index},1)) > {mid} -- "res {"id": payloa…...

Vue 项目登录的基本流程

Vue 用户登录的基本流程包括以下6个步骤&#xff1a; 步骤&#xff1a; 1. 创建登录表单 在前端&#xff0c;首先要创建一个登录表单&#xff0c;用户输入账号&#xff08;用户名、邮箱、手机号等&#xff09;和密码。 示例&#xff1a;Login.vue <template><div…...

kubernetes源码分析 kubelet

简介 从官方的架构图中很容易就能找到 kubelet 执行 kubelet -h 看到 kubelet 的功能介绍&#xff1a; kubelet 是每个 Node 节点上都运行的主要“节点代理”。使用如下的一个向 apiserver 注册 Node 节点&#xff1a;主机的 hostname&#xff1b;覆盖 host 的参数&#xff1…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

测试markdown--肇兴

day1&#xff1a; 1、去程&#xff1a;7:04 --11:32高铁 高铁右转上售票大厅2楼&#xff0c;穿过候车厅下一楼&#xff0c;上大巴车 &#xffe5;10/人 **2、到达&#xff1a;**12点多到达寨子&#xff0c;买门票&#xff0c;美团/抖音&#xff1a;&#xffe5;78人 3、中饭&a…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文通过代码驱动的方式&#xff0c;系统讲解PyTorch核心概念和实战技巧&#xff0c;涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...