深入了解Flutter的isolate(4) --- 使用isolates的方法

栏目: IOS · Android · 发布时间: 5年前

内容简介:前面讲了如何创建isolate,这篇文章讲创建了isolate之后,isolate之间如何通信。isolates之间通信方法有两种:Compute函数对isolate的创建和底层的消息传递进行了封装,使得我们不必关系底层的实现,只需要关注功能实现。

前面讲了如何创建isolate,这篇文章讲创建了isolate之后,isolate之间如何通信。

0x01 isolates之间通信方法

isolates之间通信方法有两种:

  1. 高级API:Compute函数 (用起来方便)
  2. 低级API:ReceivePort

0x02 Compute函数

Compute函数对isolate的创建和底层的消息传递进行了封装,使得我们不必关系底层的实现,只需要关注功能实现。

首先我们需要:

  1. 一个函数:必须是顶级函数或静态函数
  2. 一个参数:这个参数是上面的函数定义入参(函数没有参数的话就没有)

比如,还是计算斐波那契数列:

void main() async{
  //调用compute函数,compute函数的参数就是想要在isolate里运行的函数,和这个函数需要的参数
  print( await compute(syncFibonacci, 20));
  runApp(MyApp());
}

int syncFibonacci(int n){
  return n < 2 ? n : syncFibonacci(n-2) + syncFibonacci(n-1);
}
复制代码

运行后的结果如下:

flutter: 6765
复制代码

是不是很简单,接下来看下 compute 函数的源码,这里的代码有点复杂,会把分析的添加到代码的注释里,首先介绍一个 compute 函数里用到的函数别名:

ComputeCallback<Q, R> 定义如下:

// Q R是泛型,ComputeCallback是一个有参数Q,返回值为R的函数
typedef ComputeCallback<Q, R> = R Function(Q message);
复制代码

正式看源码:

//compute函数 必选参数两个,已经讲过了
Future<R> compute<Q, R>(ComputeCallback<Q, R> callback, Q message, { String debugLabel }) async {
  //如果是在profile模式下,debugLabel为空的话,就取callback.toString()
  profile(() { debugLabel ??= callback.toString(); });
  final Flow flow = Flow.begin();
  Timeline.startSync('$debugLabel: start', flow: flow);
  final ReceivePort resultPort = ReceivePort();
  Timeline.finishSync();
  //创建isolate,这个和前面讲的创建isolate的方法一致
  //还有一个,这里传过去的参数是用_IsolateConfiguration封装的类
  final Isolate isolate = await Isolate.spawn<_IsolateConfiguration<Q, R>>(
    _spawn,
    _IsolateConfiguration<Q, R>(
      callback,
      message,
      resultPort.sendPort,
      debugLabel,
      flow.id,
    ),
    errorsAreFatal: true,
    onExit: resultPort.sendPort,
  );
  final R result = await resultPort.first;
  Timeline.startSync('$debugLabel: end', flow: Flow.end(flow.id));
  resultPort.close();
  isolate.kill();
  Timeline.finishSync();
  return result;
}

@immutable
class _IsolateConfiguration<Q, R> {
  const _IsolateConfiguration(
    this.callback,
    this.message,
    this.resultPort,
    this.debugLabel,
    this.flowId,
  );
  final ComputeCallback<Q, R> callback;
  final Q message;
  final SendPort resultPort;
  final String debugLabel;
  final int flowId;

  R apply() => callback(message);
}

void _spawn<Q, R>(_IsolateConfiguration<Q, R> configuration) {
  R result;
  Timeline.timeSync(
    '${configuration.debugLabel}',
    () {
      result = configuration.apply();
    },
    flow: Flow.step(configuration.flowId),
  );
  Timeline.timeSync(
    '${configuration.debugLabel}: returning result',
    () { configuration.resultPort.send(result); },
    flow: Flow.step(configuration.flowId),
  );
}

## 0x03 ReceivePort
复制代码

import 'dart:async'; import 'dart:io'; import 'dart:isolate';

import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart';

//一个普普通通的Flutter应用的入口 //main函数这里有async关键字,是因为创建的isolate是异步的 void main() async{ runApp(MyApp());

//asyncFibonacci函数里会创建一个isolate,并返回运行结果 print(await asyncFibonacci(20)); }

//这里以计算斐波那契数列为例,返回的值是Future,因为是异步的 Future asyncFibonacci(int n) async{ //首先创建一个ReceivePort,为什么要创建这个? //因为创建isolate所需的参数,必须要有SendPort,SendPort需要ReceivePort来创建 final response = new ReceivePort(); //开始创建isolate,Isolate.spawn函数是isolate.dart里的代码,_isolate是我们自己实现的函数 //_isolate是创建isolate必须要的参数。 await Isolate.spawn(_isolate,response.sendPort); //获取sendPort来发送数据 final sendPort = await response.first as SendPort; //接收消息的ReceivePort final answer = new ReceivePort(); //发送数据 sendPort.send([n,answer.sendPort]); //获得数据并返回 return answer.first; }

//创建isolate必须要的参数 void _isolate(SendPort initialReplyTo){ final port = new ReceivePort(); //绑定 initialReplyTo.send(port.sendPort); //监听 port.listen((message){ //获取数据并解析 final data = message[0] as int; final send = message[1] as SendPort; //返回结果 send.send(syncFibonacci(data)); }); }

int syncFibonacci(int n){ return n < 2 ? n : syncFibonacci(n-2) + syncFibonacci(n-1); }

复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

水平营销

水平营销

[美] 菲利普·科特勒、费尔南多・德・巴斯 / 陈燕茹 / 中信出版社 / 2005-1 / 25.00元

《水平营销》阐明了相对纵向营销而言的的水平营销的框架和理论。引入横向思维来作为发现新的营销创意的又一平台,旨在获得消费者不可能向营销研究人员要求或建议的点子。而这些点子将帮助企业在产品愈加同质和超竞争的市场中立于不败之地。 《水平营销》提到: 是什么创新过程导致加油站里开起了超市? 是什么创新过程导致取代外卖比萨服务的冷冻比萨的亮相? 是什么创新过程导致巧克力糖里冒出了玩具......一起来看看 《水平营销》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换