Flutter 多线程实现
异步Isolate实现多线程
最近在看Flutter开发相关知识点,对照着Android原生,探究了下多线程实现方式。在Flutter中有 Isolate,隔离,它的实现原理并不是内存共享的,它更像是一个进程。
最简单的 compute
import 'dart:convert';
main(List<String> args) {
String jsonString = '''{ "id":"1234", "name":"hahaha"}''';
People people = parseJson(jsonString);
print(people.name);
}
Student parseJson(String json) {
Map<String, dynamic> map = jsonDecode(json);
return People.fromJson(map);
}
class People{
String id;
String name;
People({this.id, this.name});
factory People.fromJson(Map parsedJson) {
return People(id: parsedJson['id'], name: parsedJson['name']);
}
}
我们需要把上面代码放入isolate中执行
isolate
Future<People> loadPeople(String json) {
return compute(parseJson, json);
}
Student parseJson(String json) {
Map<String, dynamic> map = jsonDecode(json);
return People.fromJson(map);
}
compute是 Flutter 的 api ,帮我们封装了 isolate,使用十分简单,但是也有局限性, 它没有办法多次返回结果,也没有办法持续性的传值计算,isolate了。这个有点像AIDL和Messager的关系。import 'dart:convert';
import 'dart:isolate';
main(List<String> args) async {
await start();
}
Isolate isolate;
start() async {
//创建接收端口,用来接收子线程消息
ReceivePort receivePort = ReceivePort();
//创建并发Isolate,并传入主线程发送端口
isolate = await Isolate.spawn(entryPoint, receivePort.sendPort);
//监听子线程消息
receivePort.listen((data) {
print('Data:$data');
});
}
//并发Isolate
entryPoint(SendPort sendPort) {
String jsonString = '''{ "id":"123", "name":"张三"}''';
People people = parseJson(jsonString);
sendPort.send(people);
}
Student parseJson(String json) {
Map<String, dynamic> map = jsonDecode(json);
return People.fromJson(map);
}
class people {
String id;
String name;
People({this.id, this.name});
factory People.fromJson(Map parsedJson) {
return People(id: parsedJson['id'], name: parsedJson['name']);
}
}
isolate,那么我们就需要实现双向通信:import 'dart:isolate';
main(List<String> args) async {
// 在主线程里面
await start();
await Future.delayed(Duration(seconds: 1), () {
threadPort.send('主线程');
print('1');
});
await Future.delayed(Duration(seconds: 1), () {
threadPort.send('我也来自主线程');
print('2');
});
await Future.delayed(Duration(seconds: 1), () {
threadPort.send('end');
print('3');
});
}
Isolate isolate;
//子线程发送端口
SendPort threadPort;
start() async {
// 在主线程
//创建主线程接收端口,用来接收子线程消息
ReceivePort receivePort = ReceivePort();
//创建并发Isolate,并传入主线程发送端口
isolate = await Isolate.spawn(entryPoint, receivePort.sendPort);
//监听子线程消息
receivePort.listen((data) {
print('主线程收到来自子线程的消息$data');
if (data is SendPort) {
threadPort = data;
}
});
}
//并发Isolate
entryPoint(dynamic message) {
// 在子线程里面
//创建子线程接收端口,用来接收主线程消息
ReceivePort receivePort = ReceivePort();
SendPort sendPort;
print('==entryPoint==$message');
if (message is SendPort) {
sendPort = message;
print('子线程开启');
sendPort.send(receivePort.sendPort);
//监听子线程消息
receivePort.listen((data) {
print('子线程收到来自主线程的消息$data');
assert(data is String);
if (data == 'end') {
isolate?.kill();
isolate = null;
print('子线程结束');
return;
}
});
return;
}
}
双向通信比较复杂,所以我们需要封装下,通过 api 让外部调用:
import 'dart:async';
import 'dart:isolate';
main(List<String> args) async {
var worker = Worker();
worker.reuqest('发送消息1').then((data) {
print('子线程处理后的消息:$data');
});
Future.delayed(Duration(seconds: 2), () {
worker.reuqest('发送消息2').then((data) {
print('子线程处理后的消息:$data');
});
});
}
class Worker {
SendPort _sendPort;
Isolate _isolate;
final _isolateReady = Completer<void>();
final Map<Capability, Completer> _completers = {};
Worker() {
init();
}
void dispose() {
_isolate.kill();
}
Future reuqest(dynamic message) async {
await _isolateReady.future;
final completer = new Completer();
final requestId = new Capability();
_completers[requestId] = completer;
_sendPort.send(new _Request(requestId, message));
return completer.future;
}
Future<void> init() async {
// 在主线程里面
final receivePort = ReceivePort();
final errorPort = ReceivePort();
errorPort.listen(print);
receivePort.listen(_handleMessage);
_isolate = await Isolate.spawn(
_isolateEntry,
receivePort.sendPort,
onError: errorPort.sendPort,
);
}
void _handleMessage(message) {
if (message is SendPort) {
_sendPort = message;
_isolateReady.complete();
return;
}
if (message is _Response) {
final completer = _completers[message.requestId];
if (completer == null) {
print("Invalid request ID received.");
} else if (message.success) {
completer.complete(message.message);
} else {
completer.completeError(message.message);
}
return;
}
throw UnimplementedError("Undefined behavior for message: $message");
}
static void _isolateEntry(dynamic message) {
// 在子线程里面
SendPort sendPort;
final receivePort = ReceivePort();
receivePort.listen((dynamic message) async {
if (message is _Request) {
print('子线程收到:${message.message}');
sendPort.send(_Response.ok(message.requestId, '处理后的消息'));
return;
}
});
if (message is SendPort) {
sendPort = message;
sendPort.send(receivePort.sendPort);
return;
}
}
}
class _Request {
/// The ID of the request so the response may be associated to the request's future completer.
final Capability requestId;
/// The actual message of the request.
final dynamic message;
const _Request(this.requestId, this.message);
}
class _Response {
/// The ID of the request this response is meant to.
final Capability requestId;
/// Indicates if the request succeeded.
final bool success;
/// If [success] is true, holds the response message.
/// Otherwise, holds the error that occured.
final dynamic message;
const _Response.ok(this.requestId, this.message) : success = true;
const _Response.error(this.requestId, this.message) : success = false;
}
Flutter 多线程实现的更多相关文章
- Android开发如何准备技术面试(含Android面试押题)
今年毋庸置疑是找工作的寒冬,每一个出来找工作的同学都是值得尊敬的.现在找工作,虽然略难,但是反过来看也会逼迫我们成为更加优秀的自己. 但是不管是旺季还是寒冬,有一些优秀的同学找工作还是挺顺利的.所以说 ...
- 双非本科字节跳动Android面试经验和心得体会分享(已拿offer)
新人报道,没有什么可分享的,就记录一些自己求职的体会和心得. 我是在校招补录的时候参加了今日头条的招聘,岗位是Android开发,最后成功拿到了入场券.但是这也丝毫不值得骄傲,大家都知道:技术日新月异 ...
- 2579页阿里P8Android学习笔记在互联网上火了,完整版开放下载
笔记作者:来自于阿里P8级大神: Mark 笔记特点:条理清晰,理论+实战+源码,含图像化表示更加易懂. 内容概要:Android 相关,性能优化,Java 相关,Kotlin 相关,网络相关,插件化 ...
- 2020年!最全Android大厂面试真题合集(附答案)
这份Android面试真题涵盖了图片,网络和安全机制,网络,数据库,插件化.模块化.组件化.热修复.增量更新.Gradle,架构设计和设计模式,Android Framework .Android优秀 ...
- 说实话,Android开发月薪3W,谁不酸呢?
近期有个网友在某匿名区晒字节跳动Offfer,毕业一年月薪3W,引发众多读者羡慕,纷纷留言酸了.酸了.但进大厂的要求还是蛮高的,需要在技术实力上有一定的积累,今天给大家分享一份高质量笔记, 助力大家技 ...
- Flutter 实现原理及在马蜂窝的跨平台开发实践
一直以来,跨平台开发都是困扰移动客户端开发的难题. 在马蜂窝旅游 App 很多业务场景里,我们尝试过一些主流的跨平台开发解决方案, 比如 WebView 和 React Native,来提升开发效率和 ...
- Flutter学习一
包管理 依赖本地包 dependencies: pkg1: path: ../../code/pkg1 依赖git包 dependencies: pkg1: git: url: git://githu ...
- Flutter中通过https post Json接收Json
Flutter 已然成为炙手可热前端框架.若问跨平台到底有多香,自然是要多香有多香.今天我就分享这些天研究Flutter http连接和json格式转换的内容,小弟对Flutter也是小白一名,如有错 ...
- Flutter 简介(事件、路由、异步请求)
1. 前言 Flutter是一个由谷歌开发的开源移动应用软件开发工具包,用于为Android和iOS开发应用,同时也将是Google Fuchsia下开发应用的主要工具.其官方编程语言为Dart. 同 ...
- iOS播放器、Flutter高仿书旗小说、卡片动画、二维码扫码、菜单弹窗效果等源码
iOS精选源码 全网最详细购物车强势来袭 一款优雅易用的微型菜单弹窗(类似QQ和微信右上角弹窗) swift, UITableView的动态拖动重排CCPCellDragger 高仿书旗小说 Flut ...
随机推荐
- Java 实现OCR扫描/识别图片文字
图片内容一般无法编辑,如果想要读取图片中的文本,我们需要用到OCR工具.本文将介绍如何在Java中实现OCR识别读取图片中的文字. 所需工具: IDEA Spire.OCR for Java - Ja ...
- 创业:大模型RAG系统三个月的开发心得和思考
1. 前言 自从和员外上家公司离职后,我们就自己搞公司投入到了RAG大模型的AI产品应用的开发中,这中间有一个春节,前后的总时间大概是三个月左右,在这三个月期间,基本是昼夜兼程啊,到今天3月底结束,产 ...
- SSE与AVX指令基础介绍与使用
SSE与AVX指令基础介绍与使用 SSE/AVX指令属于Intrinsics函数,由编译器在编译时直接在调用处插入代码,避免了函数调用的额外开销.但又与inline函数不同,Intrinsics函数的 ...
- OpenHarmony系统使用gdb调试init
前言 OpenAtom OpenHarmony(简称"OpenHarmony")适配新的开发板时,启动流程init大概率会出现问题,其为内核直接拉起的第一个用户态进程,问题定位 ...
- HUAWEI DevEco Testing注入攻击测试:以攻为守,守护OpenHarmony终端安全
OpenAtom OpenHarmony(以下简称"OpenHarmony")作为面向全场景的开源分布式操作系统,可广泛应用于智能家居物联网终端.智能穿戴.智慧大屏.汽车智能座舱. ...
- c# 后端与前端时间戳的转换
C# DateTime与时间戳转换 C# DateTime与时间戳的相互转换,包括JavaScript时间戳和Unix的时间戳. 1. 什么是时间戳 首先要清楚JavaScript与Unix的时间戳的 ...
- c#程序员必学清单
必读书目:1. "Effective C#: 50 Specific Ways to Improve Your C#" by Bill Wagner2. "CLR via ...
- 力扣445(java&python)-两数相加Ⅱ(中等)
题目: 给你两个 非空 链表来代表两个非负整数.数字最高位位于链表开始位置.它们的每个节点只存储一位数字.将这两数相加会返回一个新的链表. 你可以假设除了数字 0 之外,这两个数字都不会以零开头. 示 ...
- 力扣237(java&python)-删除链表中的节点(中等)
题目: 有一个单链表的 head,我们想删除它其中的一个节点 node. 给你一个需要删除的节点 node .你将 无法访问 第一个节点 head. 链表的所有值都是 唯一的,并且保证给定的节点 n ...
- ECharts海量数据渲染解决卡顿的4种方式
场景 周五进行需求评审的时候: 出现了一个图表,本身一个图表本没有什么稀奇的: 可是产品经理在图表的上的备注,让我觉得这个事情并不简单: 那个图表的时间跨度可以是月,年,而且时间间隔很短: 这让我意识 ...