
以下文章来源于Flutter社区,作者talisk
通常来说,Flutter 技术构建的应用程序在默认情况下都是高性能的。所以你只需要避开常见的陷阱,就可以获得优异的性能,而不需要使用复杂的分析工具对细节做优化。这些最佳建议将ben
1. 最佳实践
如何设计一个能最有效地渲染页面的 Flutter 应用程序?特别是如何确保底层框架生成的绘图代码尽可能高效?这里有几件需要你在设计应用时考虑的事情:
1.1 控制 build() 方法的耗时
build() 方法中进行重复且耗时的工作,因为当父 Widget 重建时,子 Wdiget 的 build() 方法会被频繁地调用。build() 方法中返回一个过于庞大的 Widget。把他们分拆成不同的 Widget,并进行封装,另外他们要这样改变:setState()时,所有后代 Widget 都将重建。因此,将 setState() 的调用转移到其 UI 实际需要更改的 Widget 子树部分。如果改变的部分仅包含在 Widget 树的一小部分中,请避免在 Widget 树的更高层级中调用 setState()。另见:
StatefulWidget API 文档的 Performance considerations 部分。1.2 仅当需要的时候才应用效果
由于代价很大,请谨慎使用效果。一些效果的背后调用了性能代价很大的 saveLayer() 方法。
调用 saveLayer() 会开辟一片离屏缓冲区。将内容绘制到离屏缓冲区可能会触发渲染目标切换,这些切换在较早期的 GPU 中特别慢。
一些在使用效果时的通用规则:
Opacity Widget,就尽量不要用。有关将透明度直接应用于图像的示例,请参见 Transparent image,这比使用 Opacity widget 更快。saveLayer()(除非明确使用 Clip.antiAliasWithSaveLayer),因此这些操作没有 Opacity 那么耗时,但仍然很耗时,所以请谨慎使用。其他会触发 saveLayer() 的 widget,可能也会代价高昂。
ShaderMaskColorFilterChip— 当 disabledColorAlpha != 0xff 的时候,会调用 saveLayer()Text—might cause call to saveLayer() if there’s an overflowShader[Text][]— 当有 overflowShader 时,会调用 saveLayer()
避免调用 saveLayer() 的方式:
Opacity 文档。borderRadius属性。1.3 对列表和网格列表懒加载
在构建大型网格或列表时,使用带有回调的惰性方法。这样,只有屏幕的可见部分是在开始时构建的。
请参阅:
Creating a ListView that loads one page at a timeListview.builder API由于构建和渲染有两个独立的线程,因此构建时间为 16ms,60Hz 显示器上渲染时间为 16ms。如果需要考虑延迟,就要在 16ms 或更短 的时间内构建和显示帧。请注意,这意味着构建需要少于 8ms,渲染也需要少于 8ms,总计 16ms 或更短。如果需要考虑丢帧(jankyness),那么每个构建和渲染阶段的 16ms 都可以。
如果在 profile 构建 状态下,每一帧渲染时间低于 16ms,你可能不必担心性能问题以及一些性能陷阱,但仍然应该致力于尽可能快地渲染每一帧。为什么?
如果你想弄明白为什么 60fps 会带来平滑的视觉体验,请看视频 Why 60fps?
2. 陷阱
如果你需要调整应用程序的性能,或者 UI 顺畅度没达到你的预期,那么 IDE 的 Flutter plugin 可以提供帮助。在 Flutter Performance 窗口中,勾选 Show widget rebuild information 复选框。此功能可帮助你检测帧的渲染和显示时间是否超过 16ms。在可能的情况下,插件提供指向相关提示的链接。
以下行为可能会对您应用的性能产生负面影响。
Opacity widget,尤其是在动画中避免使用。请用 AnimatedOpacity 或 FadeInImage 进行代替。更多信息,请参阅 Performance considerations for opacity animation。Column() 或 ListView()),以避免构建成本。