Flutter _ 性能优化——如何避免应用 jank,Android开发热门前沿知识

本文探讨了Flutter中的Isolate使用,包括Isolate的创建、消息传递、ComputeAPI的便捷性以及其带来的性能代价,如额外时间和空间消耗,以及如何通过LoadBalancer减少isolate创建和messagecopy。作者还提供了优化建议和资源链接。
摘要由CSDN通过智能技术生成

} finally {
isolate.addOnExitListener(receivePort.sendPort,
response: “isolate has been killed”);
}
isolate?.kill();
}

我们先创建出 ReceivePort,然后在 Isolate.spawn 的时候将 receivePort.sendPort 作为 message 传入新的 isolate。

然后监听 receivePort,并打印收听到的 message。这里需要注意的是,我们需要手动调用 isolate?.kill() 来关闭这个 isolate。

输出结果:

flutter: Isolate Created!

flutter: isolate has been killed

实际上这里不写 isolate?.kill() 也会在 gc 时自动销毁 isolate。

这时候你可能会问,我们的 entryPoint 只允许有一个入参,如果我们想要执行的方法需要传入其他参数怎么办呢。

定义协议

其实很简单,我们定义一个协议就行了。比如像下面这样我们定义一个 SpawnMessageProtocol 作为 message。

class SpawnMessageProtocol{
final SendPort sendPort;
final String url;
SpawnMessageProtocol(this.sendPort, this.url);
}

协议中包含 SendPort 即可。

更方便的 Compute

刚才我们使用的 Isolate.spawn 创建 Isolate 自然会觉得太过复杂,有没有一种更好的方式呢。实际上 Flutter 已经为我们封装了一些实用方法,让我们能够更加自然地使用多线程进行处理。这里我们先创建一个需要在其他 isolate 中运行的方法。

static int _doSomething(int i) {
return i + 1;
}

然后使用 compute 在另一个 isolate 中执行该方法,并返回结果。

runComputeIsolate() async{
int i = await compute(_doSomething, 8);
print(i);
}

仅仅一行代码我们就能够让 _doSomething 运行在另一个 isolate 中,并返回结果。这种方式对使用者来说几乎没有负担,基本上和写异步代码是一样的。

代价是什么

对于我们来说,其实是把多线程当做一种计算资源来使用的。我们可以通过创建新的 isolate 计算 heavy work,从而减轻 UI 线程的负担。但是这样做的代价是什么呢?

时间

通常来说,当我们使用多线程计算的时候,整个计算的时间会比单线程要多,额外的耗时是什么呢?

  • 创建 Isolate
  • Copy Message

当我们按照上面的代码执行一段多线程代码时,经历了 isolate 的创建以及销毁过程。下面是一种我们在解析 json 中这样编写代码可能的方式。

static BSModel toBSModel(String json){}

parsingModelList(List jsonList) async{
for(var model in jsonList){
BSModel m = await compute(toBSModel, model);
}
}

在解析 json 的时候,我们可能通过 compute 把解析任务放在新的 isolate 中完成,然后把值传过来。这时候我们会发现,整个解析会变得异常的慢。这是由于我们每次创建 BSModel 的时候都经历了一次 isolate 的创建以及销毁过程。这将会耗费约 50-150ms 的时间。

在这之中,我们传递 data 也经历了 Network -> Main Isolate -> New Isolate (result) -> Main Isolate,多出来两次 copy 的操作。如果我们是在 Main 线程之外的 isolate 下载的数据,那么就可以直接在该线程进行解析,最后只需要传回 Main Isolate 即可,省下了一次 copy 操作。(Network -> New Isolate (result)-> Main Isolate)

空间

Isolate 实际上是比较重的,每当我们创建出来一个新的 Isolate 至少需要 2mb 左右的空间甚至更多,取决于我们具体 isolate 的用途。

OOM 风险

我们可能会使用 message 传递 data 或 file。而实际上我们传递的 message 是经历了一次 copy 过程的,这其实就可能存在着 OOM 的风险。

如果说我们想要返回一个 2GB 的 data,在 iPhone X(3GB ram)上,我们是无法完成 message 的传递操作的。

Tips

上面已经介绍了使用 isolate 进行多线程操作会有一些额外的 cost,那么是否可以通过一些手段减少这些消耗呢。我个人建议从两个方向上入手。

  • 减少 isolate 创建所带来的消耗。
  • 减少 message copy 次数,以及大小。

使用 LoadBalancer

如何减少 isolate 创建所带来的消耗呢。自然一个想法就是能否创建一个线程池,初始化到那里。当我们需要使用的时候再拿来用就好了。

实际上 dart team 已经为我们写好一个非常实用的 package,其中就包括 LoadBalancer

我们现在 pubspec.yaml 中添加 isolate 的依赖。

isolate: ^2.0.2

然后我们可以通过 LoadBalancer 创建出指定个数的 isolate。

Future loadBalancer = LoadBalancer.create(2, IsolateRunner.spawn);

这段代码将会创建出一个 isolate 线程池,并自动实现了负载均衡。

由于 dart 天生支持顶层函数,我们可以在 dart 文件中直接创建这个 LoadBalancer。下面我们再来看看应该如何使用 LoadBalancer 中的 isolate。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

由于篇幅原因,这份面试宝典已经被整理成了PDF文档,有需要Android面试宝典全套完整文档的麻烦点赞+点击GitHub即可获取资料免费领取方式!

本文在开源项目:GitHub中已收录,里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…

链图片转存中…(img-W8qR7pWA-1711393053264)]

本文在开源项目:GitHub中已收录,里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值