flutter性能优化总结

Flutter应用程序默认已经具有良好的性能,因此您只需要避免常见的陷阱,就可以获得出色的性能。

流畅度(提高渲染性能)

控制build()方法的耗时

  • 避免在 build() 方法中进行重复且耗时的工作,因为当父 widget 重建时,子 Wdiget 的 build() 方法会被频繁地调用。

  • 将嵌套过多的 widget拆成不同的 widget,并进行封装

  • 在构建可复用的 UI 代码时,多使用 Widget 抽取组件,而不是函数。

  • 请尽可能地在 widget 上使用 const 构造函数

    const 在 Dart 中用于声明常量,应用到 widget 中就相当于告诉 Flutter,“我这个组件不会随状态更新而改变了。”,因此达到了减少重建的效果。

    使用 const 也需要注意如下几点:

    当const 修饰类的构造函数时,它要求该类的所有成员都必须是final的。
    const 变量只能在定义的时候初始化。

尽量减少 saveLayer 的调用(调用 saveLayer() 会开辟一片离屏缓冲区)

参考:Flutter 应用性能优化最佳实践 | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter

列表优化

  • 构建大型网格或列表的时候,使用懒加载的方式也就是使用 ListView 和 GridView 的 builder 方法,尽量避免使用 ListView(children: [],) 或 GridView(children: [],)
  • 对已知的所有单元格大小固定时设置属性:itemExtent

  • 针对于可折叠的 ListView,未展开状态时,设置其 itemCount 为 0,这样 item 只会在展开状态下才进行构建,以减少页面第一次的打开构建时间。

避免使用 Opacity widget,尤其是在动画中避免使用。可以使用 AnimatedOpacity 或 FadeInImage 代替该操作。

使用 AnimatedBuilder 时,将不需要变化的widget作为 child 传递给 AnimatedBuilder,从而只构建一次。

避免在动画中裁剪,尽可能的在动画开始之前预先裁剪图像。

实现局部刷新:

  • 通过抽取widget为StateFulWidget包裹,使用setState刷新制定widget
  • 使用StreamBuilder实现局部刷
  • Provide的解决方案设定顶级Widget,然后用consumer包裹子控件,调用更新,provider可以实现跨组件访问,(跨组件访问也可以通过context向上查询,这种方式没试过)
  • ValueListenableBuilder组件:可以监听一个值,当其变化时通过builder回调能重建界面,避免使用setState刷新
  • GlobalKey实现控件的局部刷新:将需要单独刷新的widget从复杂的布局中抽离出去,然后通过传GlobalKey引用,这样就可以通过GlobalKey实现跨组件的刷新了。
  • StatefulBuilder组件:需要传入builder属性进行构造组件,在build中可以使用StateSetter改变构造子组件的状态,即可以不用创建类而实现一个局部刷新的组件
 int a = 0;int b = 0;// 1、定义一个叫做“aState”的StateSetter类型方法;StateSetter? aState;@overrideWidget build(BuildContext context) {return Scaffold(body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[// 2、将第一个“ElevatedButton”组件嵌套在“StatefulBuilder”组件内;StatefulBuilder(builder: (BuildContext context, StateSetter setState) {aState = setState;return ElevatedButton(onPressed: () {a++;// 3、调用“aState”方法对“StatefulBuilder”内部进行刷新;aState(() {});},child: Text('a : $a'),);},),ElevatedButton(onPressed: () {b++;setState(() {});},child: Text('b : $b'),),],),),);}

合理使用Keys来加速Flutter性能

通过使用Keys,开发人员可以更精确地控制Flutter小部件树的重建过程,避免不必要的重建,提高应用程序的性能和响应性。

保留状态:使用GlobalKey作为Key的一种常见用法是在需要保留小部件状态的情况下。通过在重建时将相同的GlobalKey分配给相同类型的小部件,可以确保小部件在重建后保留其先前的状态,而不会丢失用户的输入或滚动位置。

class MyWidget extends StatefulWidget {@override_MyWidgetState createState() => _MyWidgetState();
}class _MyWidgetState extends State<MyWidget> {final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();@overrideWidget build(BuildContext context) {return Scaffold(key: _scaffoldKey,// Widget content);}
}

列表中的重用:在ListViewGridView等可滚动列表中,使用Key可以帮助Flutter跟踪列表项并在数据源更改时有效地更新列表项,而无需重新创建整个列表。

ListView.builder(itemCount: items.length,itemBuilder: (context, index) {return ListTile(key: Key(items[index].id.toString()),title: Text(items[index].title),);},
)

动态添加或移除小部件:在动态添加或移除小部件时,使用Key可以帮助Flutter正确识别要添加或移除的小部件,而不会影响其他部分的布局。

List<Widget> widgets = [Container(key: Key('1'), child: Text('Widget 1')),Container(key: Key('2'), child: Text('Widget 2')),
];// Add a new widget
widgets.add(Container(key: Key('3'), child: Text('Widget 3')));// Remove a widget
widgets.removeWhere((widget) => widget.key == Key('2'));

处理高消耗操作时用 isolates,但不要过度使用

释放你不用的内存数据

使用SKSL预热

如果一个应用在第一次运行时的动画不流畅,但后来相同的动画变得流畅,那很可能是由于着色器编译引起的不流畅。

flutter run --profile --cache-sksl --purge-persistent-cache

flutter build apk --cache-sksl --purge-persistent-cache

使用代码分析工具

代码分析工具,如Flutter分析器和Lint,对于提高代码质量和减少错误和漏洞的风险非常有帮助。这些工具可以帮助识别潜在问题,防止它们成为问题,并提供改进代码结构和可读性的建议。

flutter analyze lib/

使用 RepaintBoundary

RepaintBoundary是一个 Widget ,用于将其子部件的绘制内容分离为单独的绘制层。这样做的主要目的是减少不必要的重绘操作,提高应用程序的性能。当RepaintBoundary包裹一个子部件时,该子部件及其所有子部件将被视为一个整体,即使其中的其他部分发生重绘,RepaintBoundary内的内容也不会重绘。

RepaintBoundary的主要作用包括:

  1. 减少重绘范围:通过将子部件包裹在RepaintBoundary中,可以将其视为一个整体,仅在该部件内部发生重绘时才重新绘制,而不会影响到其他部分。

  2. 性能优化:避免不必要的重绘操作,可以提高应用程序的性能,特别是在具有复杂界面或动态内容的情况下。

  3. 避免全局重绘:在某些情况下,只需要更新特定部分的UI,而不是整个界面。通过使用RepaintBoundary,可以限制重绘的范围,避免全局重绘。

  4. 边界控制:可以通过RepaintBoundary来控制重绘的边界,确保只在需要时才进行重绘操作,而不会影响到其他部分。

RepaintBoundary是一个有用的工具,可以帮助优化Flutter应用程序的性能,特别是在需要控制重绘范围和避免不必要重绘操作的情况下。在开发复杂界面或需要动态更新的应用程序时,合理使用RepaintBoundary可以提高应用程序的性能和用户体验。

应用程序的大小

执行如下命令,可以查看详细信息:

flutter build apk --analyze-size --target-platform android-arm64

  • 代码混淆
    flutter build apk --obfuscate --split-debug-info=./out/android/app.android-arm64.symbols
  • 资源文件优化

  • 避免使用过多的第三方库

  • 图片优化:1.压缩 PNG 和 JPEG 文件2.使用WebP格式替换PNG图片3.使用三方库压缩flutter_image_compress

//https://pub.dev/packages/flutter_image_compressFuture<Uint8List> testCompressFile(File file) async {var result = await FlutterImageCompress.compressWithFile(file.absolute.path,minWidth: 2300,minHeight: 1500,quality: 94,rotate: 90,);print(file.lengthSync());print(result.length);return result;}
  • 移除未使用的依赖库和资源。其中Android端

     buildTypes {release {// 移除无用的资源文件shrinkResources true// ZipAlign 优化zipAlignEnabled true// 设置混淆minifyEnabled true// Signing with the debug keys for now, so `flutter run --release` works.signingConfig signingConfigs.release}}

    minifyEnabled:是否启用代码缩减
    如果将 minifyEnabled 属性设为 true,系统会默认启用 R8 代码缩减功能。代码缩减(也称为“摇树优化”)是指移除 R8 确定在运行时不需要的代码的过程。此过程可以大大减小应用的大小,例如,当您的应用包含许多库依赖项,但只使用它们的一小部分功能时。
    shrinkResources:是否启用缩减资源
    资源缩减只有在与代码缩减配合使用时才能发挥作用。在代码缩减器移除所有不使用的代码后,资源缩减器便可确定应用仍要使用的资源。
     

  • android端可以设置cpu架构

    ndk {// armeabi:已经淘汰(0%)// armeabi-v7a:曾经主流的架构平台(20%)// arm64-v8a:目前主流架构平台(80%)abiFilters "armeabi-v7a", "arm64-v8a"
    //            abiFilters "arm64-v8a"}

       

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/804273.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

XILINX 7系列时钟资源

文章目录 前言一、时钟概要1.1、CC1.2、BUFR、BUFIO、BUFMR1.3、CMT1.4、BUFH1.5、BUFG 二、时钟路由资源三、CMT 前言 本文主要参考xilinx手册ug472 一、时钟概要 7系列FPGA时钟资源主要有CC、BUFR、BUFIO、BUFMR、CMT、BUFG、BUFH和GTE_COMMON 1.1、CC “CC”&#xff0…

代码签名证书是什么?软件签名证书功能和分类

代码签名证书是什么&#xff1f;代码签名证书&#xff08;Code Signing Certificate&#xff09;是用于对可执行文件或脚本&#xff0c;软件代码等进行数字签名&#xff0c;可验证软件发布者身份、保证软件签名后未被篡改&#xff0c;以此验证开发者身份的真实性和保护代码的完…

【QT】Qt Charts的实际使用中的一些小细节完善如:resetZoom、fitInView

在Qt中&#xff0c; 使用 Qt Charts来创建和操作图表&#xff0c;重置图表缩放状态的功能可以通过调整图表视图的缩放比例来实现。Qt Charts中的QChartView提供了相关的方法来控制图表的缩放和平移。 示例代码&#xff0c;以及如何对此功能进行扩展&#xff1a; #include <…

Go —— GMP面试题

前言 关于GMP的详细讲解请移步&#xff1a;Go —— 协程 简单介绍一下Go的GMP调度模型 0&#xff09;G&#xff1a;协程&#xff0c;M&#xff1a;系统线程&#xff0c;P&#xff1a;协程调度器 1&#xff09;通过go func() 生成一个 G 2&#xff09;G会优先放到P的本地队…

C++_List的学习

1.概述 1. list 是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代 2. list 的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向其前一个元素和后一个元素 3. list…

运营商名称 是如何显示到 手机通知栏上的?

在我们日常使用手机的过程中&#xff0c;经常会在通知栏或设置菜单中看到特定的运营商名称&#xff0c;例如"中国移动"、"中国联通"或"中国电信"等。 那么&#xff0c;这些运营商的名称是如何出现在我们手机上的呢&#xff1f;手机又是如何区分不…

软信天成:如何通过5个步骤获得高层对主数据管理项目的支持

如今&#xff0c;全球各地的组织正在采用主数据管理&#xff08;MDM&#xff09;以应对日益严峻的数据问题。然而&#xff0c;成功地实现 MDM 项目并非易事&#xff0c;这需要得到高层的全力支持。下面&#xff0c;软信天成将详细介绍五步策略&#xff0c;协助您获得高层对MDM项…

连接mysql或mariaDB报错:is not allowed to connect to this MariaDB server

1.报错信息&#xff1a;Host ‘192.168.3.91’ is not allowed to connect to this MariaDB server 2.报错原因&#xff1a;因为没有远程连接数据库的权限 一般为新创建数据库或新创建的用户没有远程连接数据库的权限&#xff0c;需要进行授权 # mysql -u root -p # use mysql…

属于我们Go语言的toString!

在 Go 语言中&#xff0c;类似于 Java 中的 toString() 方法&#xff0c;可以通过实现 String() 方法来自定义类型的字符串表示形式。这种机制使得在打印自定义类型的值时能够输出更加可读性高的字符串。在本文中&#xff0c;我们将探讨如何在 Go 中实现类似的功能&#xff0c;…

SCI一区 | Matlab实现OOA-TCN-BiGRU-Attention鱼鹰算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测

SCI一区 | Matlab实现OOA-TCN-BiGRU-Attention鱼鹰算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测 目录 SCI一区 | Matlab实现OOA-TCN-BiGRU-Attention鱼鹰算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测预测效果基本介绍模型描述程序…

基于springboot实现常州地方旅游管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现旅游管理系统演示 摘要 随着旅游业的迅速发展&#xff0c;传统的旅游信息查询方式&#xff0c;已经无法满足用户需求&#xff0c;因此&#xff0c;结合计算机技术的优势和普及&#xff0c;针对常州旅游&#xff0c;特开发了本基于Bootstrap的常州地方旅游管…

Python2.7和Python3.6共存的环境中,如何使用 Python 3.6 的 pip 安装其他包(如scikit-learn)

在开发环境中同时安装多个 Python 版本是一种常见的情况&#xff0c;本文将介绍在Python2.7和Python3.6共存的环境中&#xff0c;如何使用 Python 3.6 的 pip 安装其他包&#xff08;如scikit-learn&#xff09;。 步骤&#xff1a; 确定 Python 3.6 的 pip 路径&#xff1a; …

MacOS初识SIP——解决快捷指令sh脚本报错Operation not permitted

前言 因为一些原因&#xff0c;设计了一套快捷指令&#xff0c;中间涉及到一个sh脚本的运行&#xff0c;通过快捷指令运行时就会报错&#xff1a;operation not permitted 奇怪的是在快捷指令窗口下运行一切正常&#xff0c;但是从其他地方直接调用&#xff0c;例如通过Comma…

WebGL入门

WebGL采用HTML5中新引入的<canvas>元素(标签),它定义了网页上的绘图区域。 1、Canvas是什么 在HTML5出现之前,如果你想在网页上显示图像,只能使用HTML提供的原生方案<img>标签。用这个标签显示图像虽然简单,但只能显示静态的图片,不能进行实时绘制和渲染。…

微服务 - (狂神)

什么是微服务&#xff1a; 微服务方案&#xff1a; 1. SpringCloud NetFlix 2. Dubbo 3. SpringCloud Alibaba 解决了什么问题&#xff1a; 1. 服务过多&#xff0c;客户端怎么访问 2. 服务过多&#xff0c;服务间怎么传值 3. 服务过多&#xff0c;如何治理 4. 服务过多…

【Flutter】三个Channel(Android-java / Ios-swift)

Channel 实现与原生通信 【1】MethodChannel flutter MethodChannel官方文档 通过MethodChannel来传递数据&#xff0c;调用方法 案例 分别调用Android和Ios原生的获取电量的方法 Flutter端 实例一个MethodChannel&#xff0c; 唯一标识name&#xff0c;定义方法名称get…

UVA814 邮件传输的代理交互 解题报告

UVA814 邮件传输的代理交互 解题报告 题目链接 https://vjudge.net/problem/UVA-814 题目大意 本题的任务为模拟发送邮件时MTA&#xff08;邮件传输代理&#xff09;之间的交互。所谓MTA&#xff0c;就是email地址格式usermtaname的“后面部分”。当某人从user1mta1发送给另…

JavaScript ECMAScript标准的与时俱进:从ES6至ES14的革新之路与关键技术特性剖析

ECMAScript&#xff08;通常缩写为ES&#xff09;是一种标准化的脚本语言规范&#xff0c;由ECMA International&#xff08;前身为European Computer Manufacturers Association&#xff0c;欧洲计算机制造商协会&#xff09;制定。自1997年发布首个版本以来&#xff0c;ECMAS…

设计模式之创建型模式---建造者模式

文章目录 建造者模式概述经典的建造者模式建造者模式的变种总结 建造者模式概述 建造者模式是一种广泛使用的设计模式&#xff0c;在三方开源库和各种SDK中经常见到。建造者设计模式在四人帮的经典著作《设计模式&#xff1a;可复用面向对象软件基础》中被提及&#xff0c;它的…

搭建前后端的链接(java)

搭建前后端的链接(java) 一.前提 1.1 javaEE 搭建前后端的链接首先需要用到javaEE&#xff0c;也就是java企业版&#xff0c;也就是java后端(后端javaSE) 利用javaEE和前端交互&#xff0c;javaSE和数据库交互&#xff0c;javaSE和javaEE之间再进行交互就实现了前后端的交互…