稀土掘金 稀土掘金

Flutter开发-Isolate的创建与双向通信

小知识,大挑战!本文正在参与“ 程序员必备小知识”创作活动。

介绍

众所周知,dart是单线程模型,没有Android中多线程的概念,但并不是说不存在异步,程序中异步操作是一定存在的,所以dart中提供了一种类似线程概念的东西-isolate,与线程不同的是,多个isolate之间是隔离的,内存是不共享的,所以是不存在并发问题的,也有人称之为isolate是像进程一样的线程。Android和Dart的虚拟机模型如下: WeChatb2a3bbce2e52f005218ebc5b896c05ce.png

isolate创建

在dart中,程序在启动时,执行main方法后会默认创建一个主isolate,那么我们该如何创建一个子isolate去执行异步任务呢? isolate中自己提供了静态方法spawn来创建一个isolate,该方法中需要传入两个必传参数:

  • entryPoint:指定要在生成的isolate中调用的初始函数。
  • message: entryPoint函数中要接收的参数,通常用于传递sendPort来进行isolate通信。
void main(){
  Isolate.spawn(entryPoint, "message");
}

void entryPoint(String message){
  print(message);
}

验证内存隔离

创建了子isolate之后,我们可以验证一下不同isolate之间是内存隔离的吗?如下声明一个全局num,在main进行赋值操作,分别在main isolate和子isolate中打印num的值,通过控制台日志可以发现子isolate中是获取不到num的值的。

int num;

void main(){
  num = 1;
  Isolate.spawn(entryPoint, "message");
  print("main num $num");
}

void entryPoint(String message){
  print("entryPoint num $num");
}

image.png

isolate通信

像Android中我们使用Handler等进行线程通信,那么看下dart中isolate是如何发送接收数据的。

ReceivePort receivePort = ReceivePort();
receivePort.listen((message) {
  print(message);
});
receivePort.sendPort.send("这是通信消息");
receivePort.sendPort.send(1);

通过创建一个接收器ReceivePort,使用它的发送器sendPort发送消息,并通过receivePort的listen方法监听来接收所发送的消息。需要注意的是,send中发送的数据是不限制数据类型的。

image.png

前面说了spawn中的message参数通常是传入main isolate的sendport,从而来进行不同isolate间的通信,也就是可以理解为,我把我的发送器给你,并准备一个接收器接收发送器发送的消息,当你需要发送消息的时候通过发送器把消息发送给我就可以了:

void main(){
  ReceivePort receivePort = ReceivePort();
  Isolate.spawn(entryPoint, receivePort.sendPort);
  receivePort.listen((message) {
    print(message);
  });
}

void entryPoint(SendPort sendPort){
  // 模拟耗时操作
  Future.delayed(Duration(seconds: 2),(){
    sendPort.send("子isolate里面给你发的消息");
  });
}

image.png 如图所示,main isolate在2s后接收到了来自子isolate中发送的消息。

双向通信

上边说我们可以把main isolate的发送器传递给子isolate来实现通信,那么同样也可以把子isolate的发送器传递给main isolate,这样就可以实现双向通信。由于send方法是不限制发送的数据类型的,因此可以利用此特性当接收到main isolate数据后首先把子isolate的发送器发送过去,之后在进行其他通信数据的发送:

void main(){
  ReceivePort receivePort = ReceivePort();
  Isolate.spawn(entryPoint, receivePort.sendPort);
  receivePort.listen((message) {
    if(message is SendPort){
      print("main接收到子isolate的发送器了");
      Future.delayed(Duration(seconds: 1),(){
        message.send("main给子isolate发送的消息");
      });
    }else{
      print(message);
    }
  });
}

void entryPoint(SendPort sendPort){
  ReceivePort receivePort = ReceivePort();
  receivePort.listen((message) {
    print("子isolate接收到main的消息了:$message");
  });
  sendPort.send(receivePort.sendPort);
  // 模拟耗时操作
  Future.delayed(Duration(seconds: 2),(){
    sendPort.send("子isolate里面给main发的消息");
  });
}

如下所示,main中首先接收到了来自子isolate发送过来的发送器,然后用此发送器给子isolate发送了消息,从而实现了两端双向通信的场景。

2021-09-27 18.07.14.gif

需要格外注意的是,当不再使用接收器时,一定要及时调用receivePort.close()

isolate的状态方法

暂停:

isolate.pause(isolate.pauseCapability);

恢复:

isolate.resume(isolate.pauseCapability);

结束:

isolate.kill(priority: Isolate.immediate);

玻璃钢生产厂家汕头玻璃钢卡通雕塑艺术品桐乡玻璃钢卡通座椅雕塑义乌玻璃钢雕塑厂家定制淮北玻璃钢雕塑定做询问报价玻璃钢雕塑制作简易流程宜春大型玻璃钢雕塑批发陕西玻璃钢造型雕塑制作蒙城玻璃钢花盆花器玻璃钢雕塑卡通哪个信誉好人物玻璃钢雕塑哪家正规定制玻璃钢雕塑制作黑龙江玻璃钢人物雕塑厂家玻璃钢蔬菜雕塑哪里靠谱广东台州玻璃钢花盆价格顺德玻璃钢花盆花器小学校彩色玻璃钢雕塑玻璃钢雕塑墙价格福建喷泉雕塑玻璃钢肇庆景观雕塑玻璃钢郏县玻璃钢雕塑设计玻璃钢仿铜人物雕塑定制价格开封花朵玻璃钢彩绘雕塑玻璃钢雕塑可以保持多少年草莓雕塑玻璃钢房子南京儿童玻璃钢雕塑加工厂河北省玻璃钢雕塑哪家好湖南玻璃钢金属雕塑公司吉林景观玻璃钢雕塑联系方式雕塑用玻璃钢玻璃钢卡通动物雕塑品牌香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化