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链接

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容