赞
踩
Flutter应用程序默认已经具有良好的性能,因此您只需要避免常见的陷阱,就可以获得出色的性能。
避免在 build()
方法中进行重复且耗时的工作,因为当父 widget 重建时,子 Wdiget 的 build()
方法会被频繁地调用。
将嵌套过多的 widget拆成不同的 widget,并进行封装
在构建可复用的 UI 代码时,多使用 Widget
抽取组件,而不是函数。
请尽可能地在 widget 上使用 const
构造函数
const 在 Dart 中用于声明常量,应用到 widget 中就相当于告诉 Flutter,“我这个组件不会随状态更新而改变了。”,因此达到了减少重建的效果。
使用 const 也需要注意如下几点:
当const 修饰类的构造函数时,它要求该类的所有成员都必须是final的。
const 变量只能在定义的时候初始化。
参考:Flutter 应用性能优化最佳实践 | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter
对已知的所有单元格大小固定时设置属性:itemExtent
Opacity
widget,尤其是在动画中避免使用。可以使用 AnimatedOpacity
或 FadeInImage
代替该操作。AnimatedBuilder
时,将不需要变化的widget作为 child 传递给 AnimatedBuilder
,从而只构建一次。- int a = 0;
- int b = 0;
-
- // 1、定义一个叫做“aState”的StateSetter类型方法;
- StateSetter? aState;
-
- @override
- Widget 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小部件树的重建过程,避免不必要的重建,提高应用程序的性能和响应性。
保留状态:使用GlobalKey
作为Key
的一种常见用法是在需要保留小部件状态的情况下。通过在重建时将相同的GlobalKey
分配给相同类型的小部件,可以确保小部件在重建后保留其先前的状态,而不会丢失用户的输入或滚动位置。
- class MyWidget extends StatefulWidget {
- @override
- _MyWidgetState createState() => _MyWidgetState();
- }
-
- class _MyWidgetState extends State<MyWidget> {
- final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- key: _scaffoldKey,
- // Widget content
- );
- }
- }

列表中的重用:在ListView
或GridView
等可滚动列表中,使用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'));
如果一个应用在第一次运行时的动画不流畅,但后来相同的动画变得流畅,那很可能是由于着色器编译引起的不流畅。
flutter run --profile --cache-sksl --purge-persistent-cache
flutter build apk --cache-sksl --purge-persistent-cache
代码分析工具,如Flutter分析器和Lint,对于提高代码质量和减少错误和漏洞的风险非常有帮助。这些工具可以帮助识别潜在问题,防止它们成为问题,并提供改进代码结构和可读性的建议。
flutter analyze lib/
RepaintBoundary
是一个 Widget ,用于将其子部件的绘制内容分离为单独的绘制层。这样做的主要目的是减少不必要的重绘操作,提高应用程序的性能。当RepaintBoundary
包裹一个子部件时,该子部件及其所有子部件将被视为一个整体,即使其中的其他部分发生重绘,RepaintBoundary
内的内容也不会重绘。
RepaintBoundary
的主要作用包括:
减少重绘范围:通过将子部件包裹在RepaintBoundary
中,可以将其视为一个整体,仅在该部件内部发生重绘时才重新绘制,而不会影响到其他部分。
性能优化:避免不必要的重绘操作,可以提高应用程序的性能,特别是在具有复杂界面或动态内容的情况下。
避免全局重绘:在某些情况下,只需要更新特定部分的UI,而不是整个界面。通过使用RepaintBoundary
,可以限制重绘的范围,避免全局重绘。
边界控制:可以通过RepaintBoundary
来控制重绘的边界,确保只在需要时才进行重绘操作,而不会影响到其他部分。
RepaintBoundary
是一个有用的工具,可以帮助优化Flutter应用程序的性能,特别是在需要控制重绘范围和避免不必要重绘操作的情况下。在开发复杂界面或需要动态更新的应用程序时,合理使用RepaintBoundary
可以提高应用程序的性能和用户体验。
启动速度优化最常用的方法是空间换时间法
方式一、通过flutter引擎预加载来达到页面秒开的效果:
- /**
- * 预加载flutter
- */
- fun preLoad(context: Context) {
- //在线程空闲时执行预加载任务
- Looper.myQueue().addIdleHandler {
- initFlutterEngine(context, MODULE_NAME_FAVORITE)
- initFlutterEngine(context, MODULE_NAME_RECOMMEND)
- false
- }
- }
-
- /**
- * 获取预加载的flutter
- */
- fun getCachedFlutterEngine(moduleName: String, context: Context?): FlutterEngine {
- var engine = FlutterEngineCache.getInstance()[moduleName]
- if (engine == null && context != null) {
- engine = initFlutterEngine(context, moduleName)
- }
- return engine!!
- }
-
- /**
- * 销毁flutterengine
- */
- fun destroyCached(moduleName: String) {
- FlutterEngineCache.getInstance()[moduleName]?.apply {
- destroy()
- }
- FlutterEngineCache.getInstance().remove(moduleName)
- }
-
- fun hastCached(moduleName: String): Boolean {
- return FlutterEngineCache.getInstance().contains(moduleName)
- }
-
- /**
- * 初始化flutter
- */
- private fun initFlutterEngine(context: Context, moduleName: String): FlutterEngine {
- val flutterEngine = FlutterEngine(context)
-
- flutterEngine.dartExecutor.executeDartEntrypoint(
- DartExecutor.DartEntrypoint(
- FlutterMain.findAppBundlePath(),
- moduleName
- )
- )
-
- FlutterEngineCache.getInstance().put(moduleName, flutterEngine)
- return flutterEngine
- }

方式二、预加载dartVM
- /**
- * 预加载DartVM
- */
- fun preLoadDartVM(context: Context) {
- val flutterLoader = FlutterLoader()
- val settings = FlutterLoader.Settings()
- flutterLoader.startInitialization(context, settings)
- val mainHandler = Handler(Looper.getMainLooper())
- flutterLoader.ensureInitializationCompleteAsync(
- context, arrayOf(), mainHandler
- ) {
- HiLog.i("flutter preLoadDartVM done")
- }
- }
两种方式都是有一定的内存成本的,对内存的消耗上:引擎预加载>DartVM预加载;对启动性能的提升上:引擎预加载>DartVM预加载,所以要不要空间换时间,还要看app具体情况。如果app内存压力不大,并且预判用户接下来会访问flutter业务,那使用这个优化就能带来很好的价值;反之,则可能造成资源浪费,意义不大。
执行如下命令,可以查看详细信息:
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_compress
-
- Future<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"
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。