原文连接html
首先,在作性能调优以前,咱们应该对flutter相关基础知识有必定的了解,否则咱们无从作起,首先,咱们要了解flutter是干吗的--Flutter 是谷歌2018年发布的跨平台移动UI框架。android
而后,他相对于其余跨平台开发框架来讲,是高效的,至于他为何高效,缘由是由于:算法
他是直接调用Skia框架,而其余框架须要借助现有的原始框架来转一下,在才开始去调用Skia框架,这一来二去,确定就有所消耗,这是其一,而后,咱们还须要知道flutter的四个线程。api
分别是:性能优化
该平台的主线程。插件代码在这里运行。更多信息请参阅:iOS 的程序 (UIKit) 文档,或者 Android 的主线程 (MainThread) 文档。性能图层并不会展现该线程。bash
UI 线程在 Dart VM 执行 Dart 代码。该线程包括开发者写下的代码和 Flutter 框架根据应用行为生成的代码。当应用建立和展现场景的时候,UI 线程首先创建一个 图层树(layer tree) ,一个包含设备无关的渲染命令的轻量对象,并将图层树发送到 GPU 线程来渲染到设备上。不要阻塞这个线程!在性能图层的最低栏展现该线程。app
GPU 线程取回图层树并通知 GPU 渲染。尽管没法直接与 GPU 线程或其数据通讯,但若是该线程变慢,必定是开发者 Dart 代码中的某处致使的。图形库 Skia 在该线程运行,有时也被叫作光栅器 (rasterizer) 线程。在性能图层的最顶栏显示该线程。框架
可能阻塞 UI 或者 GPU 线程的耗时任务(大多数状况下是 I/O)。该线程并不会在性能图层中展现。函数
因此,咱们作性能优化,关心DartUI,关心GPU两个线程,掉不掉帧,卡不卡的关键,就看这两位了,并且在99%状况下,做为Flutter开发人员,咱们咱们基本上解决好,DartUI线程上的问题,就==解决了渲染性能问题。工具
为了更加直观的表示3个树的从生到死,我不得不抛出下面这幅图来
而后,咱们常常在作性能调优的时候,会用到timeline工具,你会看到这样一幅图:
如今串起来了吗,4个线程,build---layout---paint三个阶段是否是都一目了然,各发生在什么地方,什么阶段,谁先谁后。
因此,咱们说 要解决卡顿掉帧的问题,就是要解决build,layout,paint这三个阶段各函数执行耗时的问题。
首先,咱们配置下环境,这里我配置这个变量debugProfileBuildsEnabled=true
否则,我不知道build他具体作了些啥,观望台默认不会告诉我。通常来讲,放在main函数中,在runApp以前开启便可,好比我是这么干的:
这里面有一些其余须要用到的开关,能够在数据不足的时候开启,这样咱们参考的数据多些,优化的参考点就明确些。
而后,咱们执行 flutter run --profile ,请记住,咱们须要在profile模式来性能调优,debug模式由于在渲染过程当中记录了不少分析数据且加上支持热重载的特性是损失了不少性能为代价的,profile模式更加接近release模式性能。
而后跑起来了,会出现一个连接:
点一下就去了观望台了,固然,你也可使用devTools,貌似后面会取代观望台。devTools的启动姿式是:
flutter pub global activate devtools
devTools复制代码
先安装,而后在直接运行便可:
点击这个连接,会弹出一个网页来,让你输入url,这个url就是咱们那个观望台的url,所以你彷佛秒懂了,然来,devTools是在观望台的基础至上作的一个分析工具,因此,Google必定是以为观望台不大友好了,然而,遗憾的是,devTools并非特别全面,由于如今仍是preview阶段嘛,一切都会好起来的。
一般来讲,很容易发现有问题的地方,明显那个会比较宽比较长的地方就比较能够,这种一遍就能够定位页面加载比较慢了,而后咱们点击向下箭头,把他放大点看看
大概就看到了,偶,而后,咱们点击选择,在选择一个范围看看统计效果:
这时候,咱们就发现问题了,而后这个也加载了这么多个TipCacheNetWorkImage,而后每一个大概要2ms,而后我这个是一个列表页:
因此,一共就有8个这样的控件要渲染,而他,就占用8 *2.188 > 16ms
,所以咱们找到了优化点,解决这个就能够加速渲染了,这里只是举例找到存在性能瓶颈的地方,具体相关函数耗时的优化,相信你们都懂的,这就是算法相关的问题了。
一、尽可能将setState放在叶子节点,好处是build时影响范围极小,简称局部刷新
二、能不用 Opacity
Widget,就尽可能不要用,由于这货会粗发GPU一个saveLayer的指令,作Skia的大神说,这个指令至关耗时。
三、使用ListView.builder()而不是直接使用ListView()来构建列表。
四、对于频繁更新的控件(好比倒计时,秒表),使用RepaintBoundary隔离它,让他在一个独立的paint区域。
五、使用const来修饰永远不须要变动的控件。
六、优先使用StateLessWidget,而不是所有用StateFulWidget
七、使用Visibility控件替换if/else,有些小伙伴喜欢else时return一个 占位控件,须不知,这种效率是没有Visibility高效的。
参考资料
调试 Flutter 应用 - Flutter 中文文档 - Flutter 社区中文资源
files.flutter-io.cn/events/gdd2…