大規模應用開發過程中,性能管理是重中之重,其中就包括啟動速度,互動等多個方面的優化,應用包大小和渲染性能也是很重要的衡量名額。當我們提到性能時,也無外乎運作時間和占用空間這兩個話題。
本篇文章,我們主要探讨的就是如何解決應用程式包大小的問題。
應用程式大小
應用的大小是開發者和使用者都能夠直接感覺的名額。作為開發者,我們清楚地知道 APK 檔案、App Bundle 或者 IPA 之類的安裝包中包含了應用代碼、資源檔案以及運作時的所有内容,如果體積過大,則對性能影響會造成非常大的影響,不僅會占用更多空間,也可能會無法使用一些特色功能,如 Android instant apps。
預設情況下,為了支援熱重載和代碼級調試等功能,debug 版本的安裝包會天然具有較大體積,性能優化時,可以忽略這種情況。
在 Android Studio 中,打開任意 Flutter 項目,使用
flutter build apk --release
建構安裝包之後,點選
Build >> Analyze Apk
,會發現 lib 目錄的大小占整個包大小的 95% 以上,并且其中預設編譯出來的 APK 包含有 android-arm,android-arm64,android-x64 三種二進制檔案。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5iN1U2Y1YmN3EmMxU2Y3QTZyMTZ5MDO1gTZlljN4UDMz8CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
是以,各大 Android 應用商店的或者 App Store 接收到包之後還會做進一步處理,如根據使用者的機型過濾掉一些 native 庫、DPI 等。官方也推薦我們使用
flutter build appbundle
建構 Android App Bundle(.aab) 檔案,具體請看 https://developer.android.com/platform/technology/app-bundle。
對于不支援自動拆解 App Bundles 的廠商,我們可以直接使用
flutter build apk --split-per-abi
直接編譯出各平台下的拆分 APK 包:
-
/build/app/outputs/apk/release/app-armeabi-v7a-release.apk
-
/build/app/outputs/apk/release/app-arm64-v8a-release.apk
-
/build/app/outputs/apk/release/app-x86_64-release.apk
下面,我們也可以使用最新的開發工具檢查和估算 Flutter 應用程式的具體大小…
優化包體積
Flutter 1.22 之後,官方釋出了一款應用包大小的分析工具,可以幫助開發者直覺地看到應用各個子產品占用空間大小的詳細資訊。我們隻需要在建構應用時傳入
--analyze-size
參數即可使用該分析工具:
-
flutter build apk --analyze-size
-
flutter build appbundle --analyze-size
-
flutter build ios --analyze-size
-
flutter build linux --analyze-size
-
flutter build macos --analyze-size
-
flutter build windows --analyze-size
如果建構的是 Android APK 或 bundle,則還需要指定目标平台架構,可以如下這些指令:
運作結果如下:
該指令主要有兩個作用:
- 在編譯 Dart 代碼時會記錄 Dart packages 中代碼大小的使用情況。
- 輸出應用大小相關的具體細節,并将結果最終儲存在
檔案中供我們使用 DevTools 做進行分析。*-code-size-analysis_*.json
如上圖,終端中已經展示了項目中每項所占的空間大小,也可以通過
json
檔案,使用 Dart DevTools 工具繼續做更深入的分析(https://flutter.dev/docs/development/tools/devtools/overview)。
Example breakdown of app in DevTools
應用混淆
代碼混淆 (Obfuscated code) 亦稱花指令,是将計算機程式的代碼,轉換成一種功能上等價,但是難于閱讀和了解的形式的方式。通常針對的是二進制檔案。實際使用中将可以代碼中的各種元素,如變量,函數,類的名字改寫成無意義的名字,防止攻擊者會應用逆向。
—— 維基百科
要混淆 Flutter 應用程式,首先需要适配不同平台的版本:
android /iOS:Flutter 1.16.2 以後支援。
macOS:macOS(Flutter 1.13 釋出測試版)也支援在 Flutter 1.16.2 版本後混淆。
Linux / Windows:不支援
Flutter Web:不支援
本篇文章,我們主要介紹如何混淆 Dart 代碼,關于減少應用大小,我們也可以嘗試如下幾種方法:
- 删除未使用的資源(Resource Shrinking)。
- 壓縮從三方庫導入的資源。
-
混淆原生代碼(java):
修改
/android/app/build.gradle
檔案:
建立
proguard-rules.pro
檔案:
`gradle.properties:
- 壓縮 PNG 和 JPEG 等資源檔案。
- 删除不必要的第三方庫。
- 使用 .svg 格式的圖示。
Flutter 應用混淆
Flutter 應用的混淆非常簡單,隻需要在建構 release 版應用時結合使用
--obfuscate
和
--split-debug-info
這兩個參數即可。
--obfuscate --split-debug-info
用來指定輸出調試檔案的位置,該指令會生成一個符号映射表。目前支援 apk,appbundle,ios 和 ios-framework 等目标平台(macOS 和 aar 在 master 和 dev 分支中支援),如下:
flutter build apk --obfuscate --split-debug-info=//
混淆成功後,需要儲存符号映射表,以便以後需要去混淆跟蹤代碼堆棧。
相關指令的其他資訊,可以運作
flutter build apk -h
檢視,如果不支援該指令,核實 Flutter 版本,執行
flutter upgrade
更新。
讀取混淆堆棧
要調試混淆後的應用,可以執行以下兩個步驟:
- 找到符号映射表檔案。如在 Android arm64 下發生 crash,可以分析
檔案。app.android-arm64.symbols
- 運作
指令,并指定堆棧跟蹤的檔案和符号映射表檔案即可:flutter symbolize
flutter symbolize -i -d /out/android/app.android-arm64.symbols
關于 symbolize 指令的詳細資訊,可以運作 flutter symbolize -h
檢視。
下一步
使用 Flutter 支援的代碼混淆功能後,一定會在程度上減少應用程式的總大小,但這僅僅是應用優化中一個小小的環節,有關 Flutter 應用運作效率、UI 渲染相關的更多優化問題将會在之後的文章逐一探讨。
延伸閱讀 [1]
Measuring your app’s size: https://flutter.dev/docs/perf/app-size
[2]
Obfuscating The Flutter App: https://medium.com/flutterdevs/obfuscating-the-flutter-app-80a190ed7540
[3]
Reducing Flutter App Size: https://itnext.io/reducing-flutter-app-size-570db9810ebb
[4]
Build and release an Android app: https://flutter.dev/docs/deployment/android
[5]
Obfuscating dart code: https://flutter.dev/docs/deployment/obfuscate