当前位置: 首页 > 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…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

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

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

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

JS设计模式(4):观察者模式

JS设计模式(4):观察者模式 一、引入 在开发中&#xff0c;我们经常会遇到这样的场景&#xff1a;一个对象的状态变化需要自动通知其他对象&#xff0c;比如&#xff1a; 电商平台中&#xff0c;商品库存变化时需要通知所有订阅该商品的用户&#xff1b;新闻网站中&#xff0…...

快刀集(1): 一刀斩断视频片头广告

一刀流&#xff1a;用一个简单脚本&#xff0c;秒杀视频片头广告&#xff0c;还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农&#xff0c;平时写代码之余看看电影、补补片&#xff0c;是再正常不过的事。 电影嘛&#xff0c;要沉浸&#xff0c;…...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】&#xff0c;注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录&#xff08;即exe所在文件夹&#xff09;加入系统变量…...