目录:
- 背景:
Flutter
包大小分析工具(App Size)
介绍App
体积过大的影响
- Flutter App 的产物
- 1.
Android
侧的Flutter
- 2.
IOS
侧的Flutter
- 1.
- 官方
Demo
- 资源文件优化
Demo
- 三方库优化
Demo
- 资源文件优化
- 有趣的实验
- 很长的变量名会影响包大小吗?
- 长
String
会影响包大小吗? - 未使用的方法,会被优化掉吗?
as
关键字会影响包大小吗?- 导入三方
Android plugin
会影响包大小吗?
- 总结
背景:
最近在看 devtools 的源码,发现中有两个 Demo
,通过这两个 Demo
能帮助我们学习如何使用 App Size
。
Flutter 包大小分析工具(App Size)
应用程序体积工具可让您分析应用的总体积。您可以使用 Analysis 标签 来查看「体积信息」的单个快照,或使用 Diff 标签 比较使用 「体积信息」 的两个不同快照。
更多的介绍可以Analysis 标签 处看到,这里并不过多介绍。
App体积过大的影响
- 下载转化率降低
- 性能:
- 安装时间: 增加文件拷贝、
Library
解压、odex
编译时长 - 运行时内存:
Resource
资源、Library
以及Dex
类加载都会占用应用的一部分内存 - ROM 空间:闪存空间不足,很可能出现“写入放大”的情况
- 安装时间: 增加文件拷贝、
Flutter App 的产物
1、Android 侧的Flutter
产物 | 介绍 |
---|---|
libflutter.so | Flutter 引擎的C++编译产物 |
libapp.so | Flutter业务与框架的 Dart 代码编译产物、内部由四部分组成 |
flutter.jar | Flutter引擎的Java代码编译产物 |
flutter_assets | 包括图片、字体、LICENES等静态资源 |
2、IOS 侧的Flutter
产物 | 介绍 |
---|---|
Flutter | Flutter 引擎的C++编译产物 |
icudtl.dat | 国际化支持相关数据文件 |
App | Dart 业务代码AOT编译产物 |
flutter_assets | 包括图片、字体、LICENES等静态资源 |
官方优化 Demo 介绍
一、 资源优化 Demo
第一个 Demo
中,官方为我们展示了图片优化 Demo
。
未优化的 Deme
: 存在引用图片资源文件过大
的问题。
优化后的 Demo
: 通过图片压缩优化了各个图片。
Demo
页面如下图:
使用工具 diff 分析
通过下图:
我们可以看到,该工具分析出了资源文件的优化效果。
二、 三方库优化 Demo
官方为我们展示了,使用不同库实现AES
加密功能的 Demo
未优化 Demo
: 引入了encrypt 来实现 AES
加密,引入后让 App
包大小增加了 500KB
优化后 Demo
: 引入了steel_crypt实现同样的功能,相对于 未优化 缩小了 400KB
使用 diff 工具来分析以下
我相信您跟我有同样的疑问?
为什么,这两个库有什么不同吗。
encrypt 与 steel_crypt 三方库对包大小有什么影响?
我们来通过源码来对比,这两个库有什么不同?
这两个 Demo
不同的地方在于 AES
如下图:
三方库 | AES 对比 |
---|---|
encrypt | |
steel_crypt |
上面两个构造函数对比:
- encrypt: 构造函数中至少使用到了三个对象,这三个对象均是
package:pointycastle
包下定义的。 - steel_crypt:相比非常轻量,仅用
package:pointycastle
的一个对象
所以得出结论:encrypt
额外的实现了一些功能,在运行时做判断,即使我们用不到某个对象,但是它也会跳过压缩优化随着encrypt
库打入App
的包中。
有趣的实验
1. 变量名会影响包大小吗?
分别在代码中使用以下变量:
String s = '';
String ss...sss= '';// 省略若干 s
经过测试不会!
2. 长 String 会影响包大小吗?
情况一:长字符串
String s = '';
String s = 'ssss..sss';// 省略若干 s
经过测试会!
情况二:一样的字符串
String s = 'sss..sss';
String s1 = 'sss..sss';// 省略若干各种字符串
经过测试不会!
3. 未使用的方法,会被优化掉吗?
定义一个 Test
类 test()
方法引用到 dio
三方库。
在代码中仅初始化 Test
不调用 test()
方法
定义:
import 'package:dio/dio.dart';
class Test {
void test() {
Dio();
}
}
如何使用:
Widget build() {
Test();
...
}
经过测试不会! 影响包大小
那如果调用 test()
改变使用方法?
Widget build() {
Test().test();
...
}
结果如上图:会! 影响包大小。
4. as
关键字会影响包大小吗?
不使用 as
Widget build() {
Test();
... // 中间省略 100 个 Test()
Test();
}
使用 as
Widget build() {
Test() as String;
... // 中间省略 100 个 Test() as String;
Test() as String;
}
结果如上图:会! 影响包大小。
算起来 100
个 as
会影响 5.2KB
,
原因:
as
关键字执行中报错会抛出异常,我想在Dart
编译的时会把错误文案加入到代码中。突然想到 json_serializable库中大量使用了
as
关键字,会对包大小有一定影响。
5. 导入三方 Android plugin
会影响包大小吗?
permission_handler 是一个处理原生权限的 Flutter Plugin
。
测试在 dependencies
中引用的情况:
不导入permission_handler
# permission_handler: ^9.2.0
导入permission_handler
permission_handler: ^9.2.0
得出结论: classes.dex 增加会影响包大小~。
同时也得出结论App Size
工具不能分析原生classes.dex
文件
总结:
-
App Size
可以帮助我们分析Flutter App
安装包的大小,并与其他安装包做对比。可以用来做包大小监控。 -
App Size
擅长分析Dart AOT
、Flutter assets
中的文件,并能分析出代码的属性数据。分析
classes.dex
文件仅能对比大小。 -
影响包大小的几个因素:(不考虑原生的影响)
-
flutter_assets
资源文件的大小 -
代码中
as
关键字会影响包大小 -
String
会影响包大小。注:两个一样的
String
会进行复用从而减少对包大小的影响。 -
在
dependencies
引入native
插件会将插件打包到App
的classes.dex
中,即使Dart
代码被优化。 -
引入纯
Dart
库,编译时会做分析,删除无用代码。选择三方库时尽量选择轻量级一些的库。原因:可见 《三方库优化 Demo》
-