devTool | Flutter 是如何影响 App 包大小的

1,636 阅读5分钟

目录:

  • 背景:
    • Flutter 包大小分析工具 (App Size) 介绍
    • App体积过大的影响
  • Flutter App 的产物
    • 1.Android 侧的Flutter
    • 2.IOS 侧的Flutter
  • 官方 Demo
    • 资源文件优化 Demo
    • 三方库优化 Demo
  • 有趣的实验
    • 很长的变量名会影响包大小吗?
    • String 会影响包大小吗?
    • 未使用的方法,会被优化掉吗?
    • as 关键字会影响包大小吗?
    • 导入三方 Android plugin会影响包大小吗?
  • 总结

背景:

Screenshot of app size tab

最近在看 devtools 的源码,发现中有两个 Demo,通过这两个 Demo 能帮助我们学习如何使用 App Size

Flutter 包大小分析工具(App Size)

应用程序体积工具可让您分析应用的总体积。您可以使用 Analysis 标签 来查看「体积信息」的单个快照,或使用 Diff 标签 比较使用 「体积信息」 的两个不同快照。

更多的介绍可以Analysis 标签 处看到,这里并不过多介绍。

App体积过大的影响

  • 下载转化率降低
  • 性能:
    • 安装时间: 增加文件拷贝、Library 解压、odex 编译时长
    • 运行时内存: Resource 资源、Library 以及 Dex 类加载都会占用应用的一部分内存
    • ROM 空间:闪存空间不足,很可能出现“写入放大”的情况

Flutter App 的产物

1、Android 侧的Flutter

image.png

产物介绍
libflutter.soFlutter 引擎的C++编译产物
libapp.soFlutter业务与框架的 Dart 代码编译产物、内部由四部分组成
flutter.jarFlutter引擎的Java代码编译产物
flutter_assets包括图片、字体、LICENES等静态资源

2、IOS 侧的Flutter

image.png

产物介绍
FlutterFlutter 引擎的C++编译产物
icudtl.dat国际化支持相关数据文件
AppDart 业务代码AOT编译产物
flutter_assets包括图片、字体、LICENES等静态资源

官方优化 Demo 介绍

一、 资源优化 Demo

第一个 Demo 中,官方为我们展示了图片优化 Demo

未优化Deme: 存在引用图片资源文件过大的问题。

优化后Demo: 通过图片压缩优化了各个图片。

Demo 页面如下图:

image.png

使用工具 diff 分析

通过下图:

我们可以看到,该工具分析出了资源文件的优化效果。

image.png

二、 三方库优化 Demo

官方为我们展示了,使用不同库实现AES加密功能的 Demo

image.png

未优化 Demo: 引入了encrypt 来实现 AES 加密,引入后让 App 包大小增加了 500KB

优化后 Demo: 引入了steel_crypt实现同样的功能,相对于 未优化 缩小了 400KB

使用 diff 工具来分析以下

image.png

我相信您跟我有同样的疑问

为什么,这两个库有什么不同吗。

encrypt 与 steel_crypt 三方库对包大小有什么影响?

我们来通过源码来对比,这两个库有什么不同?

这两个 Demo 不同的地方在于 AES 如下图:

三方库AES 对比
encryptimage.png
steel_cryptimage.png

上面两个构造函数对比:

  • 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. 未使用的方法,会被优化掉吗?

定义一个 Testtest() 方法引用到 dio 三方库。 在代码中仅初始化 Test不调用 test() 方法

定义:

import 'package:dio/dio.dart';

class Test {
  void test() {
    Dio();
  }
}

如何使用:

Widget build() {
    Test();
    ...
}

经过测试不会! 影响包大小

那如果调用 test() 改变使用方法?

Widget build() {
    Test().test();
    ...
}

image.png 结果如上图:会! 影响包大小。

4. as 关键字会影响包大小吗?

不使用 as

Widget build() {
    Test();
    ...    // 中间省略 100 个 Test()
    Test();
}

使用 as

Widget build() {
    Test() as String;
    ...  // 中间省略 100 个 Test() as String;
    Test() as String;
}

image.png 结果如上图:会! 影响包大小。

算起来 100as 会影响 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

image.png

得出结论: classes.dex 增加会影响包大小~。

同时也得出结论App Size工具不能分析原生classes.dex文件

总结:

  1. App Size 可以帮助我们分析 Flutter App 安装包的大小,并与其他安装包做对比。可以用来做包大小监控

  2. App Size 擅长分析Dart AOTFlutter assets 中的文件,并能分析出代码的属性数据

    分析 classes.dex 文件仅能对比大小。

  3. 影响包大小的几个因素:(不考虑原生的影响)

    • flutter_assets 资源文件的大小

    • 代码中 as 关键字会影响包大小

    • String 会影响包大小。

      注:两个一样的 String 会进行复用从而减少对包大小的影响。

    • dependencies引入native插件会将插件打包到 Appclasses.dex 中,即使Dart代码被优化。

    • 引入纯 Dart 库,编译时会做分析,删除无用代码。

      选择三方库时尽量选择轻量级一些的库。原因:可见 《三方库优化 Demo》