• flutter性能优化-UI重绘


    Flutter中,UI重绘(Repaint)是指当Widget需要更新其视觉表现时,Flutter框架重新绘制Widget所对应的视图部分。UI重绘的频繁发生可能会影响应用的性能和流畅度,因此优化UI重绘是提升Flutter应用性能的重要策略之一。

    Flutter之禅 内存优化篇-阿里云开发者社区

    导致UI重绘的因素

    1. 状态变化引起的重绘: 当Widget的状态发生变化(例如状态变量更新、属性变化等),Flutter会根据新的状态重新计算并绘制Widget的视觉表现。

    2. 布局变化引起的重绘: 当父Widget的布局发生变化(例如窗口大小变化、父Widget的布局约束变化等),会导致子Widget的重新布局和重绘。

    3. 动画和过渡效果: 使用动画或过渡效果(如AnimatedContainerHero动画等)时,Flutter框架会在每帧绘制过程中更新动画状态,可能导致频繁的UI重绘。

    4. 外部输入事件: 用户交互(如点击、滑动)会触发UI更新,以响应用户操作或更新视觉反馈。

    优化策略和技巧

    为了减少不必要的UI重绘和提升性能,可以采取以下优化策略:

    1. 使用 const 构造函数: 在可能的情况下,使用 const 构造函数创建静态Widget,这样可以在编译时进行优化,减少运行时的资源消耗。

      const MyWidget(); // 使用const构造函数
      

    2. 避免不必要的Widget重建: 合理使用 Key 管理Widget,确保只在必要时才重新构建Widget。尽量避免在每次 build 方法调用时创建新的Widget对象。

    3. 使用 StatefulWidgetState 的正确方式:StatefulWidget 中,将可能变化的部分提取为 State 类的成员变量,在 setState 方法中仅更新需要变化的部分,避免整体重绘。

    4. 使用 AnimatedBuilder 对于复杂的动画,使用 AnimatedBuilder 可以控制动画的重绘范围,只更新动画部分,减少不必要的重绘。

      1. AnimatedBuilder(
      2. animation: _controller,
      3. builder: (context, child) {
      4. return Transform.rotate(
      5. angle: _controller.value * 2.0 * math.pi,
      6. child: child,
      7. );
      8. },
      9. child: Icon(Icons.refresh),
      10. );

    5. 避免过度使用不透明度(Opacity): 使用 Opacity Widget时,其子Widget可能会被整体绘制,即使其实际上是不可见的,这可能会导致不必要的绘制操作。

    6. 优化布局算法: 合理设计和使用布局算法,避免复杂的布局嵌套和计算,减少布局变化引起的重绘。

    7. 利用 RepaintBoundary 对于频繁变化但不影响其他部分的Widget,可以使用 RepaintBoundary 将其包裹起来,减少整体重绘。

      1. RepaintBoundary(
      2. child: // 需要频繁变化但不影响其他部分的Widget,
      3. );

    8. 使用性能分析工具: 使用Flutter DevTools等性能分析工具监测和分析应用的帧率、布局性能等指标,帮助定位和解决UI重绘导致的性能问题。

    通过以上优化策略和技巧,可以有效减少不必要的UI重绘,提升Flutter应用的性能和用户体验。

    在Flutter中,可以采取以下几种方法来减少UI的重绘:  

    1. 使用setState()方法进行批量更新:当需要更新多个UI元素时,可以使用setState()方法进行批量更新,而不是在每次更新时都调用setState()。这样可以减少重绘的次数,提高性能。

    2. 使用ValueNotifier和ChangeNotifier:ValueNotifier和ChangeNotifier是Flutter中的状态管理工具,它们可以通知依赖它们的Widget进行更新。通过使用ValueNotifier和ChangeNotifier,可以精确地控制UI元素的更新,避免不必要的重绘。

    3. 使用const关键字创建不可变的Widget:在创建Widget时,可以使用const关键字创建不可变的Widget。不可变的Widget在不发生变化时不会触发重绘,可以提高性能

    4. 使用ListView.builder和DataTable等构建器:当需要构建大量列表或表格时,可以使用ListView.builder和DataTable等构建器。这些构建器会按需构建当前可见的部分,而不是一次性构建所有内容,从而减少重绘的次数,提高性能。

    5. 使用Keys来避免不必要的重建:在更新Widget时,可以使用Keys来标识Widget,从而避免不必要的重建。通过给Widget设置唯一的Key,可以确保Widget只在需要时进行重建,提高性能。

    6. 使用Offstage和Opacity来隐藏Widget:当需要隐藏一个Widget时,可以使用Offstage和Opacity来进行隐藏,而不是使用Visibility。Offstage和Opacity可以直接控制Widget是否参与布局和渲染,避免不必要的重绘。

    总结起来,减少UI的重绘可以通过批量更新、使用状态管理工具、创建不可变的Widget、使用构建器、使用Keys和合理地隐藏Widget等方法来实现。根据具体的场景和需求,可以选择适合的方法来优化UI的重绘。同时,持续的测试和性能分析也是优化的关键,可以在开发过程中不断优化和改进应用的性能。

    使用provider和ChangeNotifier库可以帮助减少不必要的刷新,从而提高应用的性能。下面是一些使用provider和ChangeNotifier库减少刷新的方法:

    1. 使用ValueNotifier代替setState:在需要更新UI的地方,可以使用ValueNotifier和ValueListenableBuilder来替代setState。ValueNotifier是一个简单的可监听值的类,可以监听值的变化并通知相关的Widget进行更新。使用ValueNotifier可以精确地控制UI的更新范围,避免不必要的刷新。

    2. 使用ChangeNotifier和Provider:ChangeNotifier是一个轻量级的状态管理类,与provider库结合使用可以实现状态共享和通知机制。通过在父级Widget中创建ChangeNotifier,并将其提供给子Widget,可以将状态共享给子Widget,并在状态发生变化时通知子Widget进行更新。这样可以避免整个Widget树的刷新,只刷新与状态相关的部分。

    3. 使用Consumer和Selector:通过使用Consumer和Selector,可以更细粒度地控制UI的更新。Consumer是一个Widget,它订阅指定的ChangeNotifier,并在ChangeNotifier发生变化时进行更新。Selector可以将特定的数据从ChangeNotifier中提取出来,只在特定数据发生变化时进行更新,避免不必要的刷新。

    4. 使用不可变的数据模型:在使用ChangeNotifier时,可以使用不可变的数据模型(如immutable类或dart的内置不可变集合类型)来存储数据。不可变的数据模型可以减少不必要的变化和刷新,提高应用的性能。

    总结起来,使用provider和ChangeNotifier库可以帮助减少不必要的刷新,提高应用的性能。通过精确地控制UI的更新范围、共享状态和使用不可变的数据模型,可以避免不必要的刷新,提高应用的响应性

    使用Offstage和Opacity来隐藏Widget,而不是使用Visibility。为什么能提升性能?  

    使用 OffstageOpacity 来隐藏Widget相比使用 Visibility 可能会在一些情况下提升性能,主要是因为它们在实现上的不同点:

    Offstage vs Visibility
    1. Offstage

      • 作用: Offstage Widget根据 offstage 属性决定其子Widget是否应该在布局中绘制。
      • 性能优势:Offstageoffstage 属性为 true 时,Flutter框架会跳过其子Widget的布局和绘制过程,这意味着被隐藏的Widget不会占用布局空间,也不会消耗绘制资源。
      • 适用场景: 适用于需要完全隐藏某些Widget,以减少布局和绘制计算的场景。比如,在需要动态根据某些条件显示或隐藏Widget时,使用 Offstage 可以更高效地管理UI布局。
    2. Opacity

      • 作用: Opacity Widget通过设置 opacity 属性来控制其子Widget的透明度,从完全不透明到完全透明。
      • 性能优势: 虽然 Opacity Widget仍会参与布局和绘制,但Flutter框架能够优化绘制透明部分的方式,减少绘制的像素数量。这种优化可以降低绘制复杂度,尤其在涉及到半透明效果的UI元素时。
    3. Visibility

      • 作用: Visibility Widget根据 visible 属性决定其子Widget是否可见,但依然会保留在布局中,只是在绘制时进行控制是否可见。
      • 性能差异: 相较于 OffstageOpacity,使用 Visibility 在隐藏时仍然保留了Widget的布局空间,虽然在绘制时不可见,但仍需进行布局计算,可能会增加一定的性能消耗。
    总结
    • 性能提升的原因:
      • 使用 OffstageOpacity 能够在不同的隐藏需求下,避免无效的布局和绘制计算,尤其在动态变化的场景中表现更为优越。
      • OffstageOpacity 的设计初衷是为了提供更高效的隐藏机制,减少不必要的绘制操作,从而在特定情况下提升性能。

    因此,根据具体的UI设计和交互需求,选择合适的隐藏方式可以帮助优化Flutter应用的性能,尤其是在需要频繁切换显示状态的场景中。

  • 相关阅读:
    Python快速刷题网站——牛客网 数据分析篇(八)
    论文篇 | 2020-Facebook-DERT :利用transformers端到端的目标检测=>翻译及理解(持续更新中)
    Redis 主从复制
    MySQL数据库查询对象空值判断与Java代码示例【含面试题】
    nodejs+vue百鸟全科赏析网站
    我在Linux开发板上跑的第一个Qt程序
    Linux系统:进程控制
    简单个人静态HTML网页设计作品 基于HTML+CSS+JavaScript仿小米手机网站 html静态在线购物商城网页制作
    josn模块和ujson模块性能对比
    前端数据可视化之【Echarts介绍】
  • 原文地址:https://blog.csdn.net/opentogether/article/details/139264075