Flutter - Isolate学习

Isolate学习

模仿computer的使用方式,使用isolate封装出一个工具。

基本概念
  1. 每个isolate之间都是相互隔离的,无法共享内存,所以他们之间的通信唯一方式只能是通过Port进行,
实现流程
  1. 在主isolate创建一个子isolate,将receivePort的sendPort传递个子isolate(packageTask为子isolate的入口函数)
  // 创建管道
  ReceivePort receivePort = ReceivePort();
  // 创建新的Isolate
  Isolate isolate = await Isolate.spawn<SendPort>(packageTask, receivePort.sendPort);
  1. 在子isolate中创建另一个receivePort2,将receivePort2的sendPort通过receivePort.sendPort发送给主isolate
void packageTask(SendPort sendPort) {
  ReceivePort receivePort2 = ReceivePort();
  SendPort sendPort2 = receivePort2.sendPort;
  receivePort2.listen((data) {
    /// 监听回调,拿到主isolate的耗时操作并执行
    Function callback = data['callback'];
    /// 将执行完的结果再发送给主isolate
    sendPort.send(callback(data['message']));
  });
  /// 第2步:将receivePort2.sendPort发送个主isolate
  sendPort.send({WXIsolatePortKey: sendPort2});
}
  1. 在主isolate的监听回调中拿到receivePort2的sendport, 然后将需要执行的耗时操作函数及参数通过receivePort2的sendport发送个子Isolate
 /// 监听管道消息
    receivePort.listen((data) {
      if (data is Map<String, dynamic> && data.containsKey(WXIsolatePortKey)) {
        /// 第3步: 拿到receivePort2.sendPort
        sendPort2 = data[WXIsolatePortKey];
        /// 将参数及耗时任务通过sendPort2发送给子isolate
        Map<String, dynamic> param = {'message': arguments, 'callback': callback};
        sendPort2.send(param);
      } else {
        /// 这边收到最终执行完的结果
        result.complete(data);
        /// 拿到结果后关闭
        closeIsolate(isolate, receivePort);
      }
    }, onError: (error) {
      closeIsolate(isolate, receivePort);
    });
  1. 子isolate通过receivePort2的回调监听拿到函数及参数并调用,将函数执行的结果通过receivePort的sendPort返回给主isolate,这样就实现了耗时任务的并发进行
receivePort2.listen((data) {
    /// 第4步:
    /// 监听回调,拿到主isolate的耗时操作并执行
    Function callback = data['callback'];
    /// 将执行完的结果再发送给主isolate
    sendPort.send(callback(data['message']));
  });
完整代码
  1. 调用方式
import 'wx_isolate.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

class FirstPage extends StatefulWidget {
  @override
  _FirstPageState createState() => _FirstPageState();
}

class _FirstPageState extends State<FirstPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('title')),
      body: Center(
        child: FutureBuilder(
          // future: getDataByCompute(),
          future: getDataByIsolate(),
          builder: (ctx, snap) {
            if (snap.hasData) {
              return Text(snap.data.toString());
            }
            return CircularProgressIndicator();
          },
        ),
      ),
    );
  }

  /// isolate 测试
  Future<String> getDataByIsolate() async {
   String str =
    await WXIsolate.addIsolateTask<String>(
            timeConsumingTask, 'getName');
    return str;
  }

  /// compute 测试
  Future<String> getDataByCompute() async {
    String str = await compute(timeConsumingTask, 'getName');
    return str;
  }
  /// 耗时任务
  static String timeConsumingTask(String str) {
    // sleep(Duration(seconds: 3));
    int index = 0;
    while(index < 2000000000) {
      index ++;
    }
    return '$str : jack';
  }
}
  1. isolate封装实现
import 'dart:async';
import 'dart:isolate';

const String WXIsolatePortKey = 'WXIsolatePortKey';

/// 子isolate可以调用主isolate中定义以static修饰的静态变量(与函数)及写在类外面的全局变量(与函数)
class WXIsolate {
  static Future<dynamic> addIsolateTask<T>(Function(T) callback, T arguments) async {
    /// 创建管道
    ReceivePort receivePort = ReceivePort();
    /// 创建新的Isolate
    Isolate isolate = await Isolate.spawn<SendPort>(packageTask, receivePort.sendPort);

    /// 创建Completer,用于返回future
    final Completer<T> result = Completer<T>();
    SendPort sendPort2;
    /// 监听管道消息
    receivePort.listen((data) {
      if (data is Map<String, dynamic> && data.containsKey(WXIsolatePortKey)) {
        /// 拿到receivePort2.sendPort
        sendPort2 = data[WXIsolatePortKey];
        /// 将参数及耗时任务通过sendPort2发送给子isolate
        Map param = {'message': arguments, 'callback': callback};
        sendPort2.send(param);
      } else {
        /// 这边收到最终执行完的结果
        result.complete(data);
        /// 拿到结果后关闭
        closeIsolate(isolate, receivePort);
      }
    }, onError: (error) {
      closeIsolate(isolate, receivePort);
    });
    return result.future;
  }
}

void packageTask(SendPort sendPort) {
  ReceivePort receivePort2 = ReceivePort();
  SendPort sendPort2 = receivePort2.sendPort;
  receivePort2.listen((data) {
    /// 监听回调,拿到主isolate的耗时操作并执行
    Function callback = data['callback'];
    /// 将执行完的结果再发送给主isolate
    sendPort.send(callback(data['message']));
  });
  /// 将receivePort2.sendPort发送个主isolate
  sendPort.send({WXIsolatePortKey: sendPort2});
}

/// 关闭通道及isolate
void closeIsolate(Isolate isolate, ReceivePort receivePort) {
  receivePort.close();
  isolate?.kill(priority: Isolate.immediate);
}

完整demo链接

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,047评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,807评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,501评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,839评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,951评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,117评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,188评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,929评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,372评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,679评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,837评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,536评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,168评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,886评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,129评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,665评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,739评论 2 351

推荐阅读更多精彩内容