Flutter 异步编程利器:Future 与 Stream 深度解析

news2025/2/22 21:29:38

目录

一、Future:处理单次异步操作

1. 概念解读

2. 使用场景

3. 基本用法

3.1 创建 Future

3.2 使用 then 消费 Future

3.3 特性

二、Stream:处理连续异步事件流

1. 概念解读

2. 使用场景

3. 基本用法

3.1 创建 Stream

3.2 监听 Stream

3.3 StreamSubscription 订阅者

 3.4 Stream 广播模式

4. 特性

三、Future 与 Stream 对比

四、高级技巧与最佳实践

1. Future 的陷阱

2. Stream 的优化

五、async/await

1. 使用 Future + then() 模式

2. 使用 async + await

3. 回调地狱解决

六、总结

相关推荐


一、Future:处理单次异步操作

        在 Dart 库中随处可见 Future 对象,通常异步函数返回的对象就是一个 Future。 当一个 future 执行完后,他里面的值就可以使用了,可以使用 then() 来在 future 完成的时候执行其他代码。Future对象其实就代表了在事件队列中的一个事件的结果

1. 概念解读

  • 定义Future 表示一个可能在未来完成的 单次异步操作,并返回一个值或错误(代表了事件结果)。

  • 状态

    • 未完成(Uncompleted):操作尚未结束。

    • 已完成(Completed):

      • 成功(value):可等待多个异步结果进行后续操作:wait方法。

      • 失败(error):对异步编程的异常捕获用 try/catch 或 .catchError() 捕获异常。

2. 使用场景

  • 网络请求(如 http.get

  • 文件读写

  • 延迟任务(如 Future.delayed

  • 单次数据库查询

3. 基本用法

3.1 创建 Future

  var dio = Dio();
  //通过 Dio 库发出HTTP GET请求返回的Future
  Future future= dio.get("https://www.wanandroid.com/banner/json");

3.2 使用 then 消费 Future

void main() {
  var dio = Dio();
  //通过 Dio 库发出HTTP GET请求返回的Future
  Future future= dio.get("https://www.wanandroid.com/banner/json");
  //使用 then 消费 future 返回结果
  future.then((response){
    print("返回结果:$response");
  });
}

3.3 特性

  • 链式调用:支持通过 .then() 串联多个异步操作。

  • 错误传播:错误会沿着链式调用传递,直到被 catchError 捕获

  • 嵌套地狱:避免过度嵌套 .then(),优先使用 async/await(下面有讲)


二、Stream:处理连续异步事件流

        Future 表示稍后获得的一个数据,所有异步的操作的返回值都用 Future 来表示。但是 Future 只能表示一次异步获得的数据。而 Stream 表示多次异步获得的数据。比如 IO 处理的时候,每次只会读取一部分数据和一次性读取整个文件的内容相比,Stream 的好处是处理过程中内存占用较小。而 Future 是一次性读取整个文件的内容进来,虽然获得完整内容处理起来比较方便,但是如果文件很大的话就会导致内存占用过大的问题。

1. 概念解读

  • 定义Stream 表示一个 连续的异步事件序列,可以发射多个值(数据、错误、完成信号)。

  • 数据流:类似于“管道”,数据从生产者(如网络、传感器)流向消费者。

2. 使用场景

  • 实时聊天消息

  • 文件下载进度更新

  • 用户输入事件(如搜索框输入)

  • 传感器数据(如陀螺仪、GPS)

3. 基本用法

3.1 创建 Stream

  //创建 Stream
  Stream<List<int>> stream = File("/Users/scc/Downloads/SCCDemo.apk").openRead();

3.2 监听 Stream

  //订阅 Stream
  stream.listen((List<int> bytes) {
    print("SccFile----Stream执行"); //执行多次
  });

        listen() 其实就是订阅这个Stream,它会返回一个 StreamSubscription 订阅者。订阅者提供了取消订阅的 cancel() 等方法

3.3 StreamSubscription 订阅者

  //创建 Stream
  Stream<List<int>> stream = File("/Users/scc/Downloads/SCCDemo.apk").openRead();
  //订阅 Stream
  StreamSubscription<List<int>> listen = stream.listen((List<int> bytes) {
    print("SccFile----Stream执行"); //执行多次
  });

  listen.onData((_){
    print("替代listen函数");
  });
  listen.onDone((){
    print("结束");
  });
  listen.onError((e,s){
    print("异常");
  });
  //暂停,如果没有继续则会退出程序
  listen.pause();
  //继续
  listen.resume();

 3.4 Stream 广播模式

        Stream有两种订阅模式:单订阅和多订阅。单订阅就是只能有一个订阅者,上面的使用我们都是单订阅模式,而广播是可以有多个订阅者。通过 Stream.asBroadcastStream() 可以将一个单订阅模式的 Stream 转换成一个多订阅模式的 Stream,isBroadcast 属性可以判断当前 Stream 所处的模式。

  Stream<List<int>> stream = File("/Users/scc/Downloads/SCCDemo.apk").openRead();
  //换成一个多订阅模式的 Stream
  var broadcastStream = stream.asBroadcastStream();
  broadcastStream.listen((List<int> bytes) {
    print("SccFile----BroadcastStream执行111"); //执行多次
  });
  broadcastStream.listen((List<int> bytes) {
    print("SccFile----BroadcastStream执行222"); //执行多次
  });
  print("Stream模式:${broadcastStream.isBroadcast}");

4. 特性

  • 多值传递:可发射多个数据、错误或完成信号。

  • 冷热流(Cold/Hot Stream)

    • 冷流:每次监听时开始生成数据(如上述 countNumbers)。

    • 热流:数据生成与监听无关(如用户点击事件)。

  • 操作符:支持 mapwheredebounce 等操作符处理数据流。


三、Future 与 Stream 对比

特性FutureStream
数据次数单次结果多次事件
适用场景一次性异步操作(如 HTTP 请求)连续事件流(如聊天、实时更新)
状态管理只能完成一次可持续发射数据或错误
错误处理通过 catchError 或 try/catch通过 onError 或 StreamBuilder
核心方法then()async/awaitlisten()async*yield
内存占用较低(单次操作)较高(需维护订阅关系)

四、高级技巧与最佳实践

1. Future 的陷阱

  • 嵌套地狱:避免过度嵌套 .then(),优先使用 async/await

  • 未处理的错误:始终用 try/catch 或 .catchError() 捕获异常。

  • 不必要的异步:同步任务无需包装为 Future

2. Stream 的优化

  • 资源释放:调用 subscription.cancel() 防止内存泄漏。

  • 防抖与节流:使用 debounce 或 throttle 优化高频事件(如搜索输入)。

  • 广播流:通过 .asBroadcastStream() 支持多个监听者。

五、async/await

        使用 async + await 的代码是异步的,但是看起来很像同步代码。当我们需要获得A的结果,再执行B,时,你需要 then()->then(),合理利用 async + await 能够很好的解决回调地狱的问题。

        下面是一个简单的网络请求,不同的实现方式,结果是相同的。

1. 使用 Future + then() 模式

void main() {
  var dio = Dio();
  dio.get("https://www.wanandroid.com/banner/json").then((response) {
    print("返回结果:$response");
  });
}

2. 使用 async + await

void main() async{
  var dio = Dio();
  Response response = await dio.get("https://www.wanandroid.com/banner/json");
  print("返回结果:$response");
}

3. 回调地狱解决

import 'package:dio/dio.dart';

// void main() {
//   var dio = Dio();
//   dio.get("https://www.wanandroid.com/banner/json").then((response) {
//     print("返回结果:$response");
//     dio.get("https://www.wanandroid.com/article/list/1/json").then((s) {
//       print("返回结果:$s");
//     });
//   });
// }

void main() async{
  var dio = Dio();
  Response response = await dio.get("https://www.wanandroid.com/banner/json");
  Response response2 = await dio.get("https://www.wanandroid.com/article/list/1/json");
  print("返回结果:$response");
  print("返回结果:$response2");
}

        当然如果你觉得这种方式写着不美观可借助 Future.wait 组合两个任务,在两个任务都完成后,再利用进行后面的操作。

Iterable<Future> futures = [_getBanner(), _getArticlelist()];
await Future.wait(futures);

六、总结

  • Future 是处理 单次异步操作 的基石,适合简单、离散的任务。

  • Stream 是管理 连续事件流 的终极方案,适合实时性要求高的场景。

  • 选择依据

    • 需要单个结果? → 使用 Future

    • 需要持续更新? → 使用 Stream

        掌握二者差异并合理运用,可显著提升 Flutter 应用的响应速度和代码可维护性。在实际开发中,常结合 Future 处理单次请求,用 Stream 管理状态(如 Bloc 库)或实时数据流,以实现高效异步编程。

相关推荐

Flutter Isolate入门指南:轻松实现高效并发编程-CSDN博客文章浏览阅读1k次,点赞30次,收藏30次。在Flutter开发中,面对复杂的业务逻辑和大量的数据处理需求,如何确保应用的流畅性和响应速度成为了开发者们关注的焦点。Flutter Isolate作为一种轻量级的并发执行单元,为我们提供了解决这一问题的有效手段。本文将带你深入了解Flutter Isolate的基本概念、使用场景以及如何在Flutter项目中轻松实现高效并发编程。_flutter isolate https://shuaici.blog.csdn.net/article/details/145505453Dart 中的Mixin:提高代码重用性和模块化的利器-CSDN博客文章浏览阅读1k次,点赞22次,收藏19次。本文介绍了Dart中Mixin的概念和使用方法。Mixin是一种代码重用机制,允许开发者将一些功能混入到一个类中,而不必通过继承来实现。文章详细阐述了Mixin的定义、使用以及与继承的冲突处理。通过使用Mixin,开发者可以大大提高代码的可重用性和模块化程度,将共通的功能封装起来,在需要的地方引入,避免了重复编写相同的代码。同时,Mixin还可以将复杂的代码逻辑拆分成更小的、可管理的模块,降低了代码的复杂性,提高了代码的可读性和可维护性。 https://shuaici.blog.csdn.net/article/details/145332099

正在参与 2024 博客之星评选活动,希望大佬们多多支持,谢谢啦:
​​​​​​https://www.csdn.net/blogstar2024/detail/070

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

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

相关文章

Java短信验证功能简单使用

注册登录阿里云官网&#xff1a;https://www.aliyun.com/ 搜索短信服务 自己一步步申请就可以了 开发文档&#xff1a; https://next.api.aliyun.com/api-tools/sdk/Dysmsapi?version2017-05-25&languagejava-tea&tabprimer-doc 1.引入依赖 <dependency>…

React进阶之React核心源码解析(一)

React核心源码解析 react 特点CPU卡顿IO 卡顿 新老 react 架构对比v15v16.8Scheduler 调度器Reconciler 协调器 React fiber原理更新dommount 构建过程 render阶段 — scheduler reconcilerreact源码解析react-domreact-dom/src/client/ReactDOMRoot.js react-reconcilerreact-…

【Vue】打包vue3+vite项目发布到github page的完整过程

文章目录 第一步&#xff1a;打包第二步&#xff1a;github仓库设置第三步&#xff1a;安装插件gh-pages第四步&#xff1a;两个配置第五步&#xff1a;上传github其他问题1. 路由2.待补充 参考文章&#xff1a; 环境&#xff1a; vue3vite windows11&#xff08;使用终端即可&…

类加载机制及双亲委派模型

一、引言 二、类加载流程 1. 加载 2. 连接 2.1 验证 2.2 准备 2.3 解析 3. 初始化 三、类加载器 类加载器的类型 双亲委派模型 打破双亲委派模型 双亲委派模型优点 一、引言 在 Java 的运行机制中&#xff0c;类加载是一个至关重要的环节。它不仅决定了 Java 程序的动态…

尚硅谷课程【笔记】——大数据之Hadoop【一】

课程视频链接&#xff1a;尚硅谷Hadoop3.x教程 一、大数据概论 1&#xff09;大数据概念 大数据&#xff08;Big Data&#xff09;&#xff1a;指无法再一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合&#xff0c;是需要新处理模式才能具有更强的决策力、洞察发…

DockerFile优化镜像体积

title: DockerFile优化镜像体积 date: 2025-02-15 15:22:40 tags: DockerFile优化镜像体积DockerFile优化镜像体积 DockerFile优化镜像体积前文回顾:一、细数优化镜像体积的思路与方式二、优化Dockfile文件编辑 Dockerfile2文件三、构建镜像四、运行镜像五、查看运行效果原文 …

题解:洛谷 P4113 [HEOI2012] 采花

题目https://www.luogu.com.cn/problem/P4113 运用类似于P1972 [SDOI2009] HH的项链的操作&#xff0c;将数据离线下来处理。 按照区间右端点从小到大排序。 问题是数量大于等于 的时候才能算进去。 于是乎我们用两个数组维护倒数第二次出现和最后一次出现的地方。 每次在…

easyexcel快速使用

1.easyexcel EasyExcel是一个基于ava的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel 即通过java完成对excel的读写操作&#xff0c; 上传下载 2.easyexcel写操作 把java类中的对象写入到excel表格中 步骤 1.引入依赖 <depen…

android studio下载安装汉化-Flutter安装

1、下载android studio官方地址&#xff1a;&#xff08;这个网址可能直接打不开&#xff0c;需要VPN&#xff09; https://developer.android.com/studio?hlzh-cn mac版本分为X86和arm版本&#xff0c;电脑显示芯片是Inter的就是x86的&#xff0c;显示m1和m2的就是arm的 …

Seaweedfs(master volume filer) docker run参数帮助文档

文章目录 进入容器后执行获取weed -h英文中文 weed server -h英文中文 weed volume -h英文中文 关键点测试了一下&#xff0c;这个-volume.minFreeSpace string有点狠&#xff0c;比如设置值为10&#xff08;10%&#xff09;&#xff0c;它直接给系统只留下10%的空间&#xff0…

【工业安全】-CVE-2022-35555- Tenda W6路由器 命令注入漏洞

文章目录 1.漏洞描述 2.环境搭建 3.漏洞复现 4.漏洞分析 4.1&#xff1a;代码分析  4.2&#xff1a;流量分析 5.poc代码&#xff1a; 1.漏洞描述 漏洞编号&#xff1a;CVE-2022-35555 漏洞名称&#xff1a;Tenda W6 命令注入 威胁等级&#xff1a;高危 漏洞详情&#xff1…

C#(Winform)通过添加AForge添加并使用系统摄像机

先展示效果 AForge介绍 AForge是一个专门为开发者和研究者基于C#框架设计的, 也是NET平台下的开源计算机视觉和人工智能库 它提供了许多常用的图像处理和视频处理算法、机器学习和神经网络模型&#xff0c;并且具有高效、易用、稳定等特点。 AForge主要包括: 计算机视觉与人…

【LeetCode: 611. 有效三角形的个数 + 排序 + 双指针】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

每日十题八股-补充材料-2025年2月15日

1.TCP是如何保证消息的顺序和可靠的&#xff1f; 写得超级好的文章 首先肯定是三次握手和四次挥手保证里通讯双方建立了正确有效的连接。 其次是校验和、序列号&#xff0c;ACK消息应答机制还有重传机制&#xff0c;保证了消息顺序和可靠。 同时配合拥塞机制和流量控制机制&am…

国内已经部署DeepSeek的第三方推荐

大家好&#xff0c;我是苍何。 最近DeepSeek爆火&#xff0c;我也说点心里话&#xff0c;其实就我们普通人而言&#xff0c;要想用好 DeepSeek&#xff0c;其实无非就是要利用好工具为我们自己提效。 比如你是搞编程的&#xff0c;你就得学会如何用 DeepSeek 更快速的辅助你编…

Windows环境下使用Ollama搭建本地AI大模型教程

注&#xff1a;Ollama仅支持Windows10及以上版本。 安装Ollama 去 ollama官网 下载对应平台及OS的安装包。 运行安装包&#xff0c;点击“安装”按钮即可开始安装。Ollama会自动安装到你的 C:\Users\<当前用户名>\AppData\Local\Programs\Ollama 目录上。 安装完成后&…

2024年认证杯SPSSPRO杯数学建模A题(第二阶段)保暖纤维的保暖能力全过程文档及程序

2024年认证杯SPSSPRO杯数学建模 A题 保暖纤维的保暖能力 原题再现&#xff1a; 冬装最重要的作用是保暖&#xff0c;也就是阻挡温暖的人体与寒冷环境之间的热量传递。人们在不同款式的棉衣中会填充保暖材料&#xff0c;从古已有之的棉花、羽绒到近年来各种各样的人造纤维。不…

算法19(力扣244)反转字符串

1、问题 编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间&#xff0c;你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 2、示例 &#xff08;1&#xff09; 示例 1&a…

DeepSeek 助力 Vue 开发:打造丝滑的卡片(Card)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

ESP32 arduino + DeepSeek API访问

此项目主要使用ESP32-S3实现一个AI语音聊天助手&#xff0c;可以通过该项目熟悉ESP32-S3 arduino的开发&#xff0c;百度语音识别&#xff0c;语音合成API调用&#xff0c;百度文心一言大模型API的调用方法&#xff0c;音频的录制及播放&#xff0c;SD卡的读写&#xff0c;Wifi…