在产品的运营期间,我们发现Android用户对App容量大小的敏感度明显高于iOS用户。
所以,为了提升产品在市场中竞争力,进一步提升产品的下载量,我们需要对基于Flutter开发的Android客户端进行包体优化。
经过调研,我们发现Flutter经过多年的发展后,DevTools已经完善,用较低的低成本即可满足需求。
下面我们会从分析开始,了解不同构成部分的容量分布情况。再对构成部分的特性来决定最终如何进行包体优化。
生成分析报告
首先,在build产物时,我们可以加上 --analyze-size
标识来生成分析报告。apk 和 appbundle 还可以指定产物的平台架构,如:--target-platform android-arm
,分析实际机型的情况。
# 变异产物
# Specify one of android-arm, android-arm64, or android-x64 in the --target-platform flag.
flutter build apk --analyze-size --target-platform android-arm64
flutter build appbundle --analyze-size --target-platform android-arm64
AI 代码解读
apk 分析日志
app-release.apk (total compressed) 33 MB ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ assets/ dexopt 1 KB flutter_assets 5 MB classes.dex 7 MB lib/ arm64-v8a 18 MB Dart AOT symbols accounted decompressed size 8 MB package:flutter 3 MB package:image 799 KB dart:core 325 KB package:xxx_xxx_flutter 293 KB dart:ui 279 KB dart:typed_data 226 KB dart:io 212 KB dart:collection 177 KB package:vector_graphics_compiler 170 KB dart:async 154 KB package:flutter_localizations 129 KB package:flutter_spinkit 99 KB package:extended_image 93 KB dart:ffi 85 KB package:petitparser 73 KB dart:convert 62 KB package:archive 62 KB package:dio 57 KB package:vector_math 54 KB package:riverpod 49 KB AndroidManifest.xml 3 KB res/ -j.png 4 KB 1k.png 33 KB 1r.png 91 KB 2M.png 3 KB 33.9.png 2 KB 3m.png 1 KB 4C.png 1 KB 4F.png 10 KB AQ.png 33 KB Bj.png 29 KB CG.png 23 KB Ch.png 98 KB D2.png 14 KB E7.png 98 KB EA.png 98 KB ER.9.png 2 KB FM.9.png 1 KB Fo.png 29 KB G1.png 2 KB J6.9.png 2 KB JO.png 29 KB Mr.9.png 1 KB NF.png 6 KB Ni.png 33 KB ON.png 91 KB Pi.9.png 3 KB Q11.9.png 3 KB RX.png 16 KB S9.png 2 KB SD.png 5 KB Tu.png 10 KB Vq.png 1 KB Vw.png 71 KB WR.png 30 KB XU.png 1 KB Yj.png 4 KB _C.png 3 KB _f.png 2 KB bI.png 3 KB color-v23 2 KB color 16 KB dn.png 2 KB e1.xml 1 KB eB.9.png 2 KB fM.png 5 KB fR.png 67 KB gV.9.png 1 KB jy.png 8 KB nN.png 4 KB qt.png 2 KB tj.9.png 2 KB u3.png 3 KB wi.9.png 2 KB wi1.9.png 1 KB wn.png 10 KB x4.png 3 KB yT.png 1 KB zT.png 91 KB resources.arsc 926 KB client_analytics.proto 1 KB dc/ a.gz 37 KB kotlin/ collections 1 KB kotlin.kotlin_builtins 5 KB ranges 1 KB reflect 1 KB ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ A summary of your APK analysis can be found at: /Users/xxx/.flutter-devtools/apk-code-size-analysis_01.json To analyze your app size in Dart DevTools, run the following command: dart devtools --appSizeBase=apk-code-size-analysis_01.json
AI 代码解读
appbundle 分析日志
app-release.aab (total compressed) 18 MB ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ BUNDLE-METADATA/ assets.dexopt 1 KB com.android.tools.build.libraries 8 KB com.android.tools.build.obfuscation 628 KB base/ assets 5 MB dex 3 MB lib 8 MB Dart AOT symbols accounted decompressed size 8 MB package:flutter 3 MB package:image 799 KB dart:core 325 KB package:xxx_xxx_flutter 293 KB dart:ui 279 KB dart:typed_data 226 KB dart:io 212 KB dart:collection 177 KB package:vector_graphics_compiler 170 KB dart:async 154 KB package:flutter_localizations 129 KB package:flutter_spinkit 99 KB package:extended_image 93 KB dart:ffi 85 KB package:petitparser 73 KB dart:convert 62 KB package:archive 62 KB package:dio 57 KB package:vector_math 54 KB package:riverpod 49 KB manifest 4 KB res 1 MB resources.pb 292 KB root 51 KB META-INF/ UPLOAD.SF 46 KB UPLOAD.RSA 1 KB MANIFEST.MF 34 KB ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ A summary of your AAB analysis can be found at: /Users/xxx/.flutter-devtools/aab-code-size-analysis_01.json To analyze your app size in Dart DevTools, run the following command: dart devtools --appSizeBase=aab-code-size-analysis_01.json ✓ Built build/app/outputs/bundle/release/app-release.aab (18.2MB).
AI 代码解读
解读分析报告
使用DevTools解读报告
这里以 VS Code DevTools 举例(Install and run DevTools from VS Code)
shift + cmd + p
打开命令面板,再输入Open DevTools
,打开面板。选择App Size Tooling,打开,并选择需要分析的文件,路径在生成报告时会提供(如:/Users/xxx/.flutter-devtools/aab-code-size-analysis_01.json)
以上图为例,appbundle在未压缩的情况下, 体积为23.1MB,其中base占据了主要的容量。
base中占据主要大小的分别有lib (8MB)、assest (5MB)、dex (3MB)、res (1.2MB)。
分析内容物可以得出:
- lib,Flutter端的代码实现以及依赖库。
- assets,Flutter端使用到的资源文件。
- dex,原生端的代码实现以及依赖库。
- res,原生端使用到的资源文件。
除去这些主要的文件内容,剩余的多位配置文件,所占容量的比例也不大,可优化空间不大。
可探索的优化方向
第一步,通过优化素材可以直接减少包体内容的大小。
降低视频素材的分辨率和质量
多使用jpg、svg等高压缩率的图片素材
使用IconFont替换icon的图片素材
使用网络素材,替换本地素材,比如使用网络图片/视频,网络素材包等。
使用GoogleFonts替代本地Fonts。
第二步,减少不必要的代码模块。
- 检查 pubspec.yaml 并删除未使用的库/包。
- 对第三方库进行精简定制,再引入使用,删除不需要的功能。
- 使用Flutter提供的精简代码功能,对产物代码进行重定义。
下面介绍下Flutter提供的精简代码功能。
精简代码
在build产物时,添加 --obfuscate
和 --split-debug-info
来实现对代码的混淆,以及对代码的精简。
--split-debug-info
,提取调试信息,实现精简代码,可单独使用。--obfuscate
,开启代码混淆,提高代码反编译门槛。
# 指定android-arm64平台,在当前路径输出符号表(如`app.android-arm64.symbols`)
flutter build appbundle --target-platform android-arm64 --split-debug-info=.
AI 代码解读
未精简的日志
flutter build appbundle --target-platform android-arm64 Running Gradle task 'bundleRelease'... Font asset "MaterialIcons-Regular.otf" was tree-shaken, reducing it from 1645184 to 3124 bytes (99.8% reduction). Tree-shaking can be disabled by providing the --no-tree-shake-icons flag when building your app. Running Gradle task 'bundleRelease'... 26.7s ✓ Built build/app/outputs/bundle/release/app-release.aab (18.2MB).
AI 代码解读
精简后的日志
flutter build appbundle --target-platform android-arm64 --split-debug-info=. Running Gradle task 'bundleRelease'... Font asset "MaterialIcons-Regular.otf" was tree-shaken, reducing it from 1645184 to 3124 bytes (99.8% reduction). Tree-shaking can be disabled by providing the --no-tree-shake-icons flag when building your app. Running Gradle task 'bundleRelease'... 56.6s ✓ Built build/app/outputs/bundle/release/app-release.aab (17.6MB).
AI 代码解读
开启混淆的日志
flutter build appbundle --target-platform android-arm64 --split-debug-info=. --obfuscate Running Gradle task 'bundleRelease'... Font asset "MaterialIcons-Regular.otf" was tree-shaken, reducing it from 1645184 to 3124 bytes (99.8% reduction). Tree-shaking can be disabled by providing the --no-tree-shake-icons flag when building your app. Running Gradle task 'bundleRelease'... 57.5s ✓ Built build/app/outputs/bundle/release/app-release.aab (17.6MB).
AI 代码解读
读取混淆的堆栈跟踪
如需要调试被混淆的应用程序创建的堆栈跟踪,请遵循以下步骤将其解析为可读的内容:
找到与应用程序匹配的符号文件。例如,在 Android arm64 设备崩溃时,需要
app.android-arm64.symbols
文件。向
flutter symbolize
命令提供堆栈跟踪(存储在文件中)和符号文件。例如:
flutter symbolize -i <stack trace file> -d out/android/app.android-arm64.symbols
AI 代码解读
总结
在素材和代码模块的两个方向上进行包体优化,是比较容易操作,并且不会影响App稳定性的方案。
在出包的工作流中,我们会启用精简代码以及代码混淆,优化产物中代码所占的体积。
排查已经引入的依赖库,看是否存在未使用或者已经弃用的多余依赖。同时分析占容量较大的三方依赖,判断是否需要通过精简定制来降低容量。
最终是排查素材,筛选体积,对不达标的素材进行重新制作,或者寻找替代方案,比如改用网络资源。