如何在Futter开发中做性能优化?
目录
1. 避免不必要的Widget重建
问题:频繁调用setState()导致整个Widget树重建。
优化策略:
2. 高效处理长列表
问题:ListView一次性加载所有子项导致内存暴涨。
优化策略:
3. 图片加载优化
问题:加载高分辨率图片导致内存溢出。
优化策略:
4. 动画性能优化
问题:复杂动画导致UI卡顿。
优化策略:
5. 状态管理优化
问题:全局状态变化导致无关Widget重建。
优化策略:
6. 避免阻塞UI线程
问题:主线程执行耗时操作导致界面卡顿。
优化策略:
7. 使用性能分析工具
工具:Flutter DevTools
总结:性能优化检查表
案例分析
在Flutter开发中,性能优化是提升应用流畅度和用户体验的关键。但是对于没怎么接触过这方面的同学来说,可能对性能优化的理解还比较基础,这就需要从多个方面入手。首先,我们需要回顾一下之前学过的关于Flutter性能优化的知识点,比如三棵树、Widget生命周期、状态管理等,然后结合实际的开发场景,找到常见的性能问题及其解决方法。
以下从多个方面详细解释性能优化策略,并配合具体示例说明:
1. 避免不必要的Widget重建
首先,我记得在Flutter中,Widget的重建是非常频繁的,尤其是在使用setState时。如果每次重建都创建大量的新对象,可能会导致垃圾回收频繁,从而影响性能。因此,避免在build方法中创建不必要的对象是一个重要的优化点。比如使用const构造函数,或者将一些对象缓存起来重复使用。
问题:频繁调用setState()导致整个Widget树重建。
优化策略:
-
使用
const构造函数:减少相同Widget的重复创建。
// 优化前:每次重建都会创建新的Text
Text('Hello')// 优化后:使用const缓存实例
const Text('Hello')
-
拆分Widget:将静态部分提取为独立的
StatelessWidget。
class StaticPart extends StatelessWidget {const StaticPart({super.key});@overrideWidget build(BuildContext context) {return const Text('Static Content');}
}
2. 高效处理长列表
接下来是关于列表的优化。当处理长列表时,比如ListView,如果不使用builder来构建,可能会导致所有的子Widget一次性加载到内存中,这显然对性能不利。而ListView.builder可以按需构建子项,只渲染当前可见的部分,这样可以减少内存的使用和渲染时间。另外,给列表项添加key也是一个优化点,尤其是当列表项有状态时,正确的key可以帮助Flutter更好地复用已有的Element,减少重建的开销。
问题:ListView一次性加载所有子项导致内存暴涨。
优化策略:
-
使用
ListView.builder:按需构建可见项。
ListView.builder(itemCount: 1000,itemBuilder: (context, index) => ListTile(title: Text('Item $index'),),
)
-
添加
itemExtent:固定子项高度,提升滚动性能。
ListView.builder(itemExtent: 80, // 明确指定高度// ...
)
-
使用
keys复用状态:确保动态列表项状态正确保留。
ListView.builder(itemBuilder: (context, index) => ListItem(key: ValueKey(items[index].id)),
)
3. 图片加载优化
然后是图片加载的优化。图片资源如果处理不当,比如加载高分辨率的图片而没有适当压缩,可能会导致内存占用过高,甚至引起应用卡顿或崩溃。使用缓存机制,比如cached_network_image包,可以缓存网络图片,减少重复下载的开销。另外,调整图片的尺寸和分辨率以适应实际显示需求,也能有效减少内存使用。
问题:加载高分辨率图片导致内存溢出。
优化策略:
-
使用
cached_network_image:缓存网络图片,避免重复下载。
CachedNetworkImage(imageUrl: 'https://example.com/image.jpg',placeholder: (context, url) => CircularProgressIndicator(),errorWidget: (context, url, error) => Icon(Icons.error),
)
-
调整图片分辨率:使用
ResizeImage缩小图片尺寸。
Image(image: ResizeImage(FileImage(File('path/to/image.jpg')),width: 200,height: 200,),
)
4. 动画性能优化
动画和复杂UI的优化也是关键。比如使用AnimatedBuilder而不是setState来驱动动画,可以避免不必要的Widget重建。另外,对于复杂的绘制操作,可以考虑使用CustomPaint和Canvas来直接绘制,而不是组合多个Widget,这样可以减少Widget树的结构复杂度,提升渲染性能。
问题:复杂动画导致UI卡顿。
优化策略:
-
使用
AnimatedBuilder:分离动画逻辑与UI构建。
AnimationController _controller;@override
Widget build(BuildContext context) {return AnimatedBuilder(animation: _controller,builder: (context, child) => Transform.rotate(angle: _controller.value * 2 * pi,child: child,),child: const Icon(Icons.refresh),);
}
-
预加载动画资源:在
initState中初始化动画控制器。
@override
void initState() {super.initState();_controller = AnimationController(vsync: this,duration: Duration(seconds: 1),)..repeat();
}
5. 状态管理优化
状态管理方面,选择合适的状态管理方案也能影响性能。例如,使用Provider或GetX等状态管理工具进行局部状态管理,可以避免全局状态变化引起的整个Widget树重建。合理分割状态的作用域,只在需要的地方监听状态变化,减少重建的范围。
问题:全局状态变化导致无关Widget重建。
优化策略:
-
使用
Provider或 GetX等工具进行局部更新:仅通知依赖状态的组件。
// 使用Provider选择器减少重建
Consumer<AppState>(selector: (_, state) => state.counter,builder: (context, counter, _) => Text('$counter'),
)
-
避免在
build中创建回调函数:缓存函数引用。
class _MyWidgetState extends State<MyWidget> {void _handleClick() => print('Clicked');@overrideWidget build(BuildContext context) {return ElevatedButton(onPressed: _handleClick, // 使用类方法而非匿名函数child: Text('Button'),);}
}
6. 避免阻塞UI线程
还有,避免在build方法中进行耗时操作,比如同步的IO操作或复杂计算,这些操作会阻塞UI线程,导致界面卡顿。应该将这些操作移到异步任务中执行,或者使用Isolate来并行处理。
问题:主线程执行耗时操作导致界面卡顿。
优化策略:
-
使用
compute或Isolate:将计算密集型任务移至后台。
void _heavyCalculation() {compute(backgroundTask, data).then((result) {setState(() => _result = result);});
}static int backgroundTask(int data) {// 耗时计算return data * 2;
}
7. 使用性能分析工具
另外,使用Flutter的性能分析工具,如DevTools,可以帮助定位性能瓶颈。通过查看帧率、GPU和CPU的使用情况,可以找出哪些部分的代码执行时间过长,从而有针对性地进行优化。
工具:Flutter DevTools
-
功能:
-
CPU Profiler:定位耗时函数。
-
Memory:检测内存泄漏。
-
Frame Chart:分析渲染帧率。
-
-
使用步骤:
-
运行应用时执行
flutter run --profile。 -
打开DevTools(
flutter pub global run devtools)。 -
连接设备并分析性能数据。
-
总结:性能优化检查表
| 优化方向 | 具体措施 | 示例场景 |
|---|---|---|
| Widget构建 | 使用const、拆分Widget、避免冗余重建 | 静态内容、频繁更新的组件 |
| 列表处理 | ListView.builder、itemExtent、keys | 长列表、动态数据 |
| 图片加载 | 缓存、调整尺寸、懒加载 | 网络图片、图库应用 |
| 动画优化 | AnimatedBuilder、预加载控制器 | 复杂转场、粒子效果 |
| 状态管理 | 局部状态、选择器监听 | 表单输入、用户偏好设置 |
| 异步任务 | compute、Isolate | 数据解析、文件操作 |
通过结合具体场景应用上述策略,可显著提升Flutter应用的性能表现!!
案例分析
在实际开发中,可能会遇到一些具体的问题,比如页面跳转时的卡顿,或者某个复杂动画不流畅。这时候需要具体问题具体分析,结合上述的优化策略,逐步排查和调整。
例如,假设有一个页面,里面有一个垂直滚动的ListView,每个列表项都包含一张图片和一些文本。当快速滚动时,发现有明显的卡顿现象。这时候,我们可能需要检查以下几点:
- 是否使用了ListView.builder而不是ListView,确保列表项是按需构建的。
- 图片是否使用了缓存,比如cached_network_image,避免重复下载。
- 图片的尺寸是否合适,是否加载了过大的图片导致内存压力。
- 列表项的Widget结构是否过于复杂,是否有不必要的嵌套,可以尝试简化布局。
- 是否给列表项添加了唯一的key,帮助Flutter复用已有的Element。
通过逐一排查这些问题,并应用相应的优化措施,应该能够提升列表滚动的流畅度。
再比如,一个包含复杂动画的页面,动画过程中出现卡顿。
这时需要检查动画的实现方式,是否使用了高效的动画组件,如使用AnimatedContainer或显式动画控制器(AnimationController),并确保在动画过程中不会触发整个Widget树的重建。如果动画是通过不断调用setState来更新状态,可能需要改为使用AnimatedBuilder,将动画的逻辑与UI构建分离,减少重建的范围。
此外,对于频繁更新的状态,比如游戏中的实时数据,可以考虑使用更高效的状态管理方案,或者将部分计算移到Isolate中执行,避免阻塞UI线程。
总的来说,性能优化需要从多个方面综合考虑,包括Widget的构建、列表的处理、图片的加载、动画的实现、状态管理以及异步任务的处理等。通过合理的设计和优化,可以显著提升Flutter应用的流畅度和响应速度。
相关文章:
如何在Futter开发中做性能优化?
目录 1. 避免不必要的Widget重建 问题:频繁调用setState()导致整个Widget树重建。 优化策略: 2. 高效处理长列表 问题:ListView一次性加载所有子项导致内存暴涨。 优化策略: 3. 图片加载优化 问题:加载高分辨率…...
仿Ant Design Vue风格自定义浏览器滚动条样式
仿Ant Design Vue风格自定义浏览器滚动条样式 问题原因 浏览器默认的滚动条样式很丑,无法满足需求,需要自定义滚动条样式,参考ant-design-vue的样式 css修改滚动相关属性可查阅官方文档 选择器介绍 ::webkit-scrollbar:滚动条…...
Spring Boot与Apache Ignite集成:构建高性能分布式缓存和计算平台
1. 前言 1.1 什么是Apache Ignite Apache Ignite是一个高性能的分布式内存计算平台,支持内存缓存、分布式计算、流处理和机器学习等功能。它提供了低延迟的数据访问和强大的计算能力,适用于需要高性能和可扩展性的应用。 1.2 为什么选择Apache Ignite 高性能:Ignite利用内…...
OpenCV中文路径图片读写终极指南(Python实现)
文章目录 OpenCV中文路径图片读写终极指南(Python实现)一、问题深度解析1.1 现象观察1.2 底层原因 二、中文路径读取方案2.1 终极解决方案(推荐)2.2 快速修复 三、中文路径保存方案3.1 通用保存函数3.2 使用示例 四、技术原理详解…...
单元测试、系统测试、集成测试、回归测试的步骤、优点、缺点、注意点梳理说明
单元测试、系统测试、集成测试、回归测试的梳理说明 单元测试 步骤: 编写测试用例,覆盖代码的各个分支和边界条件。使用测试框架(如JUnit、NUnit)执行测试。检查测试结果,确保代码按预期运行。修复发现的缺陷并重新测…...
《CircleCI:CircleCI:解锁软件开发持续集成(CI)和持续部署(CD)高效密码》:此文为AI自动生成
《CircleCI:CircleCI:解锁软件开发持续集成(CI)和持续部署(CD)高效密码》:此文为AI自动生成 一、CircleCI 初印象 在当今软件开发的快节奏赛道上,持续集成(CIÿ…...
网络安全反渗透 网络安全攻防渗透
网络渗透防范主要从两个方面来进行防范,一方面是从思想意识上进行防范,另一方面就是从技术方面来进行防范。 1.从思想意识上防范渗透 网络攻击与网络安全防御是正反两个方面,纵观容易出现网络安全事故或者事件的公司和个人,在这些…...
《GitHub网路访问不稳定:解决办法》:此文为AI自动生成
《GitHub网路访问不稳定:解决办法》:此文为AI自动生成 GitHub 网路访问不稳定初现 在当今数字化时代,软件开发行业蓬勃发展,GitHub 作为全球最大的代码托管平台,已然成为无数开发者不可或缺的 “宝库”。它不仅汇聚了…...
G-Star 公益行 | 温暖相约 3.30 上海「开源×AI 赋能公益」Meetup
你是否曾想过,在这个数字化浪潮席卷的时代,公益组织如何突破技术瓶颈?当 AI 成为热门话题,它能为公益事业带来怎样的温度?开源的力量,如何让每一份善意都拥有无限可能? G-Star 公益行ÿ…...
docker pull 镜像问题
问题一:pull镜像报错:time out 分析:源问题,网络不稳定,更换加速源,地址:/etc/docker/daemon.json 解决:更换地址,如下,然后敲:docker daemon-reload &&…...
【Go】字符串相关知识点
字符串(String)是 Go 语言中最常用的数据类型之一,广泛应用于文本处理、数据解析、网络通信等场景。Go 语言的字符串是不可变的 UTF-8 字节序列,在性能和安全性方面与其他编程语言有所不同。 源代码 package main//字符类型 byt…...
STAR Decomposition 一种针对极端事件的信号分解方法 论文精读加复现
STAR 分解🚀 在时序预测任务中,为了情绪化信号的各种成分,例如趋势信息季节信息等往往都需要对信号进行分解。目前熟知的分解方式有很多种,经验模态分解 EMD 变分模态分解 VMD ,还有 集合经验模态分解 EEMD,…...
基于SpringBoot + Vue 的房屋租赁系统
基于springboot的房屋租赁管理系统-带万字文档 SpringBootVue房屋租赁管理系统 送文档 本项目有前台和后台两部分、多角色模块、不同角色权限不一样 共分三种角色:用户、管理员、房东 管理员:个人中心、房屋类型管理、房屋信息管理、预约看房管理、合…...
Excel中国式排名,3种方法!
大家好,我是小鱼。 什么是中国式排名呢? 举个例子比如说公司一共有10名员工进行成绩考核,如果9个人考核成绩都是90分,你是89分,按照国际惯用的排名法则:9 个人考核成绩并列第一,你第10名&…...
Flutter:跑马灯公告栏
组件 import dart:async; import package:flutter/material.dart; import package:ducafe_ui_core/ducafe_ui_core.dart;class MarqueeNotice extends StatefulWidget {/// 公告数据列表,每条公告包含title和descfinal List<Map<String, String>> notic…...
Jmeter下载及环境配置
Jmeter下载及环境配置 java环境变量配置配置jdk环境变量检查是否配置成功JMeter下载 java环境变量配置 访问地址: https://www.oracle.com/cn/java/technologies/downloads/ 注意:需要自己注册账号 下载完成,解压后的目录为: …...
【初级篇】如何使用DeepSeek和Dify构建高效的企业级智能客服系统
在当今数字化时代,企业面临着日益增长的客户服务需求。使用Dify创建智能客服不仅能够提升客户体验,还能显著提高企业的运营效率。关于DIfy的安装部署,大家可以参考之前的文章: 【入门级篇】Dify安装+DeepSeek模型配置保姆级教程_mindie dify deepseek-CSDN博客 AI智能客服…...
OpenCV特征提取与深度学习CNN特征提取差异
一、特征生成方式 OpenCV传统方法 手工设计特征:依赖人工设计的算法(如SIFT、FAST、BRIEF)提取图像中的角点、边缘等低层次特征,需手动调整参数以适应不同场景。数学驱动:基于梯度变化、几何变换等数学规…...
微信小程序threejs三维开发
微信小程序threejs开发 import * as THREE from three; const { performance, document, window, HTMLCanvasElement, requestAnimationFrame, cancelAnimationFrame, core, Event, Event0 } THREE .DHTML import Stats from three/examples/jsm/libs/stats.module.js; im…...
关于在vue3中使用keep-live+component标签组合,实现对指定某些组件进行缓存或不缓存的问题
今天收到一个需求,在vue3写的动态组件条件下,要对指定的几个vue组件进行缓存。 我们用到了keep-livecomponent标签进行动态的渲染 可以通过exclude(排除)和include(包含)来进行指定缓存 <el-tabs v-model"activeName" type"card"…...
[Java实战]性能优化qps从1万到3万
一、问题背景 事情起因是项目上springboot项目提供的tps达不到客户要求,除了增加服务器提高tps之外,作为团队的技术总监,架构师,技术扛把子,本着我不入地狱谁入地狱的原则,决心从代码上优化,让客户享受到飞一般的感觉。虽然大多数编程工作在写下第一行代码时已经完成…...
30天学习Java第四天——设计模式
设计模式概述 设计模式是一套被广泛接受的、经过试验的、可反复使用的基于面向对象的软件设计经验总结,它是开发人员在软件设计时,对常见问题的解决方案的总结和抽象。 一句话就是,设计模式是针对软件开发中常见问题和模式的通用解决方案。 …...
HTML块级元素和内联元素(简单易懂)
在HTML中,元素可以分为块级元素(Block-level elements)和内联元素(Inline elements)。这两类元素在页面布局和样式应用上有不同的特点和用途。 一、块级元素(Block-level elements) 1. 定义 …...
Webpack 和 Vite 的主要区别
Webpack 和 Vite 的主要区别,从构建机制、开发体验、生产优化等多个维度进行对比: 1. 构建机制与速度 Webpack 全量打包:启动时必须分析所有模块依赖关系,进行全量打包,生成 Bundle 文件。项目越大,冷启动时…...
大数据-spark3.5安装部署之standalone模式
真实工作中还是要将应用提交到集群中去执行,Standalone模式就是使用Spark自身节点运行的集群模式,体现了经典的master-slave模式。集群共三台机器,具体如下 u22server4spark: master worker u22server4spark2: worke…...
技术视界|构建理想仿真平台,加速机器人智能化落地
在近期的 OpenLoong 线下技术分享会 上,松应科技联合创始人张小波进行了精彩的演讲,深入探讨了仿真技术在机器人智能化发展中的关键作用。他结合行业趋势,剖析了现有仿真平台的挑战,并描绘了未来理想仿真系统的设计理念与实现路径…...
AutoGen多角色、多用户、多智能体对话系统
2023-03-11-AutoGen 使用【autoGenchainlitdeepSeek】实现【多角色、多用户、多智能体对话系统】 1-核心思路 01)技术要点:autoGenchainlitdeepSeek02)什么是autoGen->autogen是微软旗下的多智能体的框架03)什么是chainlit-&g…...
SQL99 多表查询
内连接: select name, depart_name, city from employee e join department d on e.depart_id d.depart_id join location l on d.locat_id l.locat_id; 外连接 注:本图取自博客园大佬"anliux"的博客,原帖链接:【学…...
ubuntu20.04装nv驱动的一些坑
**1.一定要去bios里面关闭secure boot,否则驱动程序需要签名,安装了的驱动无法被识别加载 2.假如没有关闭secure boot然后装了驱动,然后再去关闭secure boot,可能会导致进入不了ubuntu的情况 此时,先恢复secure boot&…...
sql靶场5-6关(报错注入)保姆级教程
目录 sql靶场5-6关(报错注入)保姆级教程 1.第五关 1.步骤一(闭合) 2.步骤二(列数) 3.报错注入深解 4.报错注入格式 5.步骤三(数据库表名) 6.常用函数 7.步骤四(表…...
