遇到两个问题:

  1. 官方 子 isolate 内不能使用插件. 解决方案: 使用 isolate_handler / flutter_isolate 代替官方 isolate 参考链接
  2. 子 isolate 处理完耗时操作, 传递结果给主 isolate 的方法: void send(Object? message); 耗时严重, 达秒级, 顿了一下, 页面才刷新的感觉( 未解决 )

Dart 单线程异步怎么实现的?

Dart 是单线程语言. Flutter 依赖于Dart
Dart的 “线程” 是指 isolate.
isolate 与线程的区别: isolate 之间是内存独立的, isolateA 不能访问isolateB的内存数据.
Future 可以实现异步.异步但串行非并发执行任务
单线程并不是说 Dart 只有一个线程! Dart可以创建子 isolate 实现多线程.

loop内有两个FIFO队列

  • microask queue
  • event queue (里面就是Future任务)

前者执行优先级高于后者, 如图

future / async / await

官方async-await描述

1. future 是Future 的实例对象, future 代表一个异步操作的结果, 它有两种状态: 未完成和已完成.
2. await 可以修饰函数/, 如果该函数返回值为Future 类型, 则会阻塞当前流程, 等待被修饰的函数执行完成后继续执行后续代码. 函数内使用 await 的前提是该函数是一个 async 函数. 也就是说 await 要和 async 配对使用.
3. 但是 async 函数内可以没有 await 关键字.

总结: await future 会阻塞流程

一: 关于async 函数:

  1. 函数内有阻塞流程(await future)的操作, 则函数会返回一个 future 实例
    (1) 如果该函数本身有返回值, 比如类型为T, 则返回类型为Future<T.>
    (2) 如果该函数本身没有返回值, 则返回类型为 Future<void.>

    比如下面的 funcTest 函数会返回 Future<void.>

    funcTest() async {await Future((){  print('funcTest end');});
    }
    

二 async 和 await 的执行流程

一个async函数同步运行直到第一个 await关键字。这意味着在async函数体内,第一个await关键字之前的所有同步代码都会立即执行
版本说明: 在 Dart 2.0 之前,async函数立即返回,不执行async函数体内的任何代码。

例子:

void main() async {print('main begin'); funcB();print('main end');
}
funcB() async {print('funcB begin'); await Future.delayed(Duration(seconds: 2), (){print('funcB delayed over'); }); print('funcB end');
}

funcB 虽然是异步函数, 但是在main函数执行到funcB时并不会跳过去打印’main end’, 而是继续执行funcB , 直到遇到funcB的第一个await关键字后返回.
打印结果:
main begin
funcB begin
main end
funcB delayed over
funcB end

Future 实现异步

官方event-loop描述

1. 立刻把任务加入 event queue, 用 Future():
// Adds a task to the event queue.
new Future(() {
// …code goes here…
});
2. some time 后把任务加入(并非执行!) event queue用 Future.delayed():
// After a one-second delay, adds a task to the event queue.
new Future.delayed(const Duration(seconds:1), () {
// …code goes here…
});
注意: Future 或 Future.delayed 的返回值是Future<T.>类型还是 Future<void.> 类型, 取决于执行函数有无返回值, 有返回值就是前者, 无返回值就是后者; 可以把执行函数理解成上文的异步函数

执行main函数:

  1. main begin
  2. funcA 是同步函数, 正常执行
    (1) funcA
  3. 这时到了funcB, 进入函数内同步执行, 直到遇到第一个await返回. 同时把函数内Future.delay添加到 event queue 队尾. 并立刻往下执行 funcC
    (1) funcB begin
  4. funcC 是 async 函数, 虽然调用时使用了await 关键字, 但是 funcC 函数内部没有阻塞流程的代码, 不会返回future. 这里 await funcC(); 等同于 funcC();
    (1) funcC begin
    (2) 2s后把执行函数加入 event loop
    (3) funcC end
  5. funcD 与 funcC 不同的是, 方法内的 Future.delayed 调用时使用了 await, 则funcD 返回一个 future, 且会阻塞funcD 函数体, 等Future.delayed 执行函数完成才会打印 ‘funcD end’
    又因为 main 函数 await funcD(); 所以要等 funcD 函数全部执行完成, 才会打印 'main end’
    (1) funcD begin
    (2) 2s后把执行函数加入 event loop
    (3) Future.delay 执行函数完成 打印 funcD end
  6. main 函数处于等待 funcD的状态, 开始loop, 因为我们没有往microtask queue 添加任务, 所以串行执行(非并发!!!) event queue
    此时 event queue 的任务:
    funcB.Future.delayed
    funcC.Future.delayed
    funcD.Future.delayed
    FIFO原则
    (1) funcB delayed over
    (2) funcB end 这里我的理解是, ‘funcB end’ 被放在了’funcB delayed over’的 then 回调里, ‘funcB delayed over’ 完成后立刻执行 ‘funcB end’ 然后才 loop下一个任务
    (3) funcC delayed over
    (4) funcD delayed over
    (5) mainEnd
void main() async {print('main begin'); funcA();funcB();await funcC();await funcD();print('main end');
}
funcA() {print('funcA');
}
funcB() async {print('funcB begin'); // 2s后把执行函数加入 event loop, 且执行函数变成完成状态才会执行下面的 'funcB end'await Future.delayed(Duration(seconds: 2), (){print('funcB delayed over'); }); print('funcB end');
}
funcC() async {print('funcC begin'); // 2s后把执行函数加入 event loopFuture.delayed(Duration(seconds: 2), (){print('funcC delayed over'); }); print('funcC end');
}
funcD() async {print('funcD begin'); // 2s后把执行函数加入 event loop, 且执行函数变成完成状态才会执行下面的 'funcD end'await Future.delayed(Duration(seconds: 2), (){print('funcD delayed over'); }); print('funcD end');
}

isolate

我们平时写的代码就运行在flutter创建好的UI线程. 当运行耗时代码时页面会有卡顿感, 就是掉帧了.
解决方案: 开辟新线程处理耗时操作, 把处理结果传给 UI 线程刷新页面.
Dart 开辟新线程的方式是使用 isolate.
isolate 与普通线程的区别在于: isolate之间是内存隔离的!!!.
比如: isolate A 内不能访问 isolate B 的变量

此时好像就结束了, 但是! 官方isolate有一个致命局限性…
我们自己创建的isolate内是没办法使用插件的. 原因是Platform-Channel的通信只能在主isolate内执行
在Stack Overflow 发现两个插件, 可以完美解决这个问题:

  1. isolate_handler
  2. flutter_isolate

但是当我感觉终于要看到胜利的曙光时我发现,
这个方法耗时达秒级(把子isolate执行完毕的结果发送给主isolate)

abstract class SendPort implements Capability {/// Sends an asynchronous [message] through this send port, to its/// corresponding `ReceivePort`.////// The content of [message] can be: primitive values/// (null, num, bool, double, String), instances of [SendPort],/// and lists and maps whose elements are any of these./// List and maps are also allowed to contain cyclic references.////// In the special circumstances when two isolates share the same code and are/// running in the same process (e.g. isolates created via [Isolate.spawn]),/// it is also possible to send object instances (which would be copied in the/// process). This is currently only supported by the/// [Dart Native](https://dart.dev/platforms#dart-native-vm-jit-and-aot)/// platform.////// The send happens immediately and doesn't block.  The corresponding receive/// port can receive the message as soon as its isolate's event loop is ready/// to deliver it, independently of what the sending isolate is doing.void send(Object? message);
}

如果这样, isolate的使用场景就变得很少了, 也只能后台任务不需要刷新页面的情况下使用了

参考: futures-isolates-event-loop

flutter 单线程异步 及 isolate 使用过程遇到的问题相关推荐

  1. python生成器单线程_【Python】迭代器、生成器、yield单线程异步并发实现详解

    转自http://blog.itpub.net/29018063/viewspace-2079767 大家在学习python开发时可能经常对迭代器.生成器.yield关键字用法有所疑惑,在这篇文章将从 ...

  2. flutter中compute和isolate

    async和await: 对于普通的任务,使用async和await可实现异步处理任务,而async的处理方式并非使用的是多线程,而是依然在UI线程中处理任务,是在同一个线程上的并发操作. 对于比较繁 ...

  3. JS定时器和单线程异步特性

    首先要说的是,定时器相关的方法都是属于BOM方法,而定时器呢,它是用于在设定的时 间执行一段代码,或者在给定的时间间隔内重复该代码.具体函数: setTimeout(callback, delay); ...

  4. 【Python】单线程异步多线程多进程实例

    上一篇文章主要介绍了多任务场景下单线程异步.多线程.多进程如何选择,链接:多任务场景下单线程异步多线程多进程 这里主要通过三个实例去验证一下简单的多任务场景下,三种方式的耗时情况,假设有10个互不关联 ...

  5. Ajax异步请求原理和过程

    Ajax异步请求原理和过程 1.什么是Ajax 2.AJAX创建异步对象XMLHttpRequest ( 考虑兼容性 ) 3.操作XMLHttpRequest 对象 1.什么是Ajax Ajax是一种 ...

  6. js 异步执行_js执行过程你了解多少?

    来公众号:「九零后重庆崽儿」找我,一起学前端. 本文首发在: js执行过程你了解多少? - 重庆崽儿brand的个人主页​www.brandhuang.com 文章自己整理自网络,如有问题欢迎在知乎或 ...

  7. flutter入门之理解Isolate及compute ——解决耗时操作卡住UI的问题

    这篇文章将会讲解flutter中的Isolate,这有助于帮你解决某些耗时计算问题导致的卡顿. 一 . 原始代码 为什么要Isolate,我们先看一段比较简单的代码: import 'package: ...

  8. java单线程异步_Java 实现异步调用

    首先 我遇到的问题是 接口调用时需要更新缓存 而更新缓存又是个说快不快的过程 所以打算做异步调用 返回我所需要的结果即可 ,至于缓存什么时候更新完 就不是我所需要关注的了 废话不多说 上代码 publ ...

  9. Flutter FutureBuilder 异步UI神器

    一般程序员都会了解,类似于 IO.网络请求等都应该是异步的. 在Dart中,我们使用 Future 来管理,这样就不用担心线程或者死锁的问题. 那么当 Flutter 涉及到 Future 的时候,w ...

  10. Flutter StreamBuilder 异步更新数据

    题记 -- 执剑天涯,从你的点滴积累开始,所及之处,必精益求精. Flutter是谷歌推出的最新的移动开发框架. [x1]微信公众号的每日提醒 随时随记 每日积累 随心而过 [x2]各种系列的视频教程 ...

最新文章

  1. python扩展库安装
  2. 用python pandas按块读取超大csv/txt
  3. STM32的CAN总线的接收双FIFO使用方法
  4. 为服务器端控件添加js.net
  5. [BZOJ1087][SCOI2005]互不侵犯King
  6. 解决ssh7.4升级8.5后环境变量失效和无法登录问题
  7. ejb运行程序_在哪里可以运行EJB?
  8. python爬取的内容不是中午_大年初六中午,全国各区县哪里最冷?
  9. mysql 配置文件my-default.cnf
  10. C#算法设计查找篇之05-二叉树查找
  11. Istio服务网格路由入门
  12. SQL数据分析-淘宝用户行为
  13. 英文文献pdf转成中文
  14. 看完不会你揍我!!Pytorch利用文本数据建立自己的数据集- Dataset Dataloader详解 附案例
  15. 20220422web前端面试记录
  16. 数据文件储存服务器入什么科目,云服务器会计上入什么科目
  17. Redis实战demo
  18. podman 使用初
  19. 中国大数据金融中心崛起:贵州落子大数据
  20. 错误码429是什么错误?

热门文章

  1. python 字母查找
  2. Mock.js数据模拟,rap2、postman可视化接口平台,Vue框架的接口链接应用
  3. 调频广播信号覆盖质量智能监测系统
  4. ParticleEmitter旧粒子系统退役 2018新粒子系统
  5. excel两行数据匹配【vlookup、countif】
  6. pythonIED -pycharm基础知识
  7. 基于改进Bisenet的五官精确分割系统(源码&教程)
  8. Android集成Bmob后端云
  9. 【前端开发】代码结构及性能优化大总结
  10. ofbiz——工作流学习笔记一(xpdl)