天天看點

Jetpack Compose 使用前後對比

Jetpack Compose 使用前後對比

為了包含 Jetpack Compose 1.0.0-beta05 的更新内容,這篇文章在第一次釋出後做出了更新。如果您希望檢視 原始版本,請點選 這裡。

2020 年,我開始了緩慢遷移 Tivi UI 的任務,目标是使其轉為由 Jetpack Compose 編寫。大約 12 個月之後,任務完成!????

在本文中,我們将會回顧并對比一些關鍵名額,以了解 Compose 相對的優勢,其中包括: APK 大小、建構速度、代碼行數。

在我們進一步了解 Compose 的相關内容前,先讓我快速地描述一下應用本身。

Tivi 已經高度子產品化,它每個 UI 的界面都在其自身的 Gradle 子產品中 (名為 ui-$NAME)。每個界面都使用 Fragment 實作,随後在主 app 子產品中使用 AndroidX Navigation 将它們結合起來。為了讓您對架構有一個直覺印象,下面是應用的子產品圖:

Jetpack Compose 使用前後對比

△ Tivi 的子產品圖,使用 Jake Wharton 所提供的,十分友善的 Gradle 任務 生成

由于導航圖使用 深度連結 URI 實作,大多數 Fragment 彼此之間一無所知,進而保證了解耦。或許更為重要的是,這種形式支援獨立子產品編譯,進而有助于進行并行建構。

注意: Tivi 的子產品結構并不完美。其中,UI 子產品 (位于頂層) 與基礎子產品 (位于底層) 間仍有許多依賴。理想情況下,每個層級應當保持分離。我接下來的工作正是要優化這一問題。

在開始遷移至 Compose 之前,Tivi 已經使用了 Android 開發者可以使用的所有炫酷 UI 元件,包括但不限于: Data Binding、Epoxy、Material Design Components、Insetter DBX、MotionLayout。但不幸的是,其中的許多元件使用了注解處理,因而也帶來了額外的建構消耗。

前面我曾提到,我們已經完成了遷移的 "第一幕",這話是什麼意思呢?現在的應用看起來與我在 2020 年二月開始遷移時别無二緻。

應用的子產品化意味它可以分片完成遷移,每次隻用遷移一個 Fragment——而這也是近 11 個月以來 46 個拉取請求 中所做的事。

我從一個簡單的界面: 劇集詳情 開始遷移,接下來是 演出詳情、"發現"、"搜尋"、"關注的演出" 等等。最近在 Paging3 支援了 Compose 後,我遷移了最後的界面: "清單" 網格:

Jetpack Compose 使用前後對比

△ 遷移前後,Tivi 中展示視訊的效果

應用遷移的第一個階段使用了 Fragments 與 Navigation,同時每個 Fragment 的 UI 使用了 Jetpack Compose 實作。

第二個 (也是最後一個) 階段是從 Fragment 遷出,并直接使用 Navigation Compose 元件。這一步在 這個 PR 中完成。

遷移的過程對我來說輕而易舉,毫無疑問 Compose 便是 Android UI 開發的未來。

下面,讓我們看看具體名額… ????

針對下列的每一個名額,我們都對比了應用的三個不同版本:

接入 Compose 前 : 回到 2020 年 2 月,這是我為 Tivi 添加 Comepse 支援的第一個 PR 釋出之前的 送出。

Fragments + Compose : 此版本所基于的 送出,被标記為遷移第一階段的結尾。我檢出了新的分支,并将 Jetpack Compose 更新到 1.0.0-beta05、AGP 更新到 7.0.0-alpha14、Gradle 更新到 7.0 以及 Kotlin 更新到 1.4.32,以減少比較中的不确定因素。您可以在 本分支 中看到相關的代碼。

完全接入 Compose : 這一版本使用了目前最新的主 送出。此時的 Tivi 已經完全基于 Compose (版本 1.0.0-beta05) 了,同時在整個應用中都沒有 Fragment。

您的使用者最為關心的名額,莫過于 APK 大小。

下面是開啟了 資源縮減 的最小化釋出版 APK (使用了 R8) 通過 APK Analyzer 所測量的結果:

Jetpack Compose 使用前後對比

△ 展示 Tivi APK 大小的圖表

Jetpack Compose 使用前後對比

△ 展示 Tivi 方法數的圖表

關于上述數字的說明:

我們使用了 APK Analyzer 報告的 "APK file size" (而不是下載下傳時的大小)。

APK 大小分析

在将遷移後的應用與接入 Compose 前的應用做比較後,我們發現 APK 大小縮減了 41%,方法數減少了 17%。

在使用了 Compose 後,我們發現 APK 大小縮減了 41%,方法數減少了 17%

這一數字表明,當您需要保留所有 View 類,以防出現需要在布局檔案中使用它們的情況時,壓縮工具的作用十分有限。

我知道在比較軟體項目時,計算源代碼行數不是特别有用的統計方式;但這種方式能夠提供一個視角,幫助我們了解事物是如何變化的。

為了進行測試,我使用了 cloc 工具。使用下面的指令可以排除各種建構檔案、自動生成檔案以及配置檔案。

Jetpack Compose 使用前後對比

△ 展示 Tivi 源代碼行數的圖表

cloc 内建支援忽略注釋的功能 (雖然我沒有進行驗證),是以上面的結果适用于實際的 "代碼"。毫不意外的,XML 行數大幅減少了 76%。再見了,布局檔案,以及 styles、theme 等其他的 XML 檔案????。

有趣的是,Kotlin 代碼的總行數也下降了。我對此現象的了解是,現在應用中的模闆代碼減少了,同時我們也得以移除大量的視圖輔助類和工具類代碼。您可以看到,我在 這個 PR 中删除了多年來編寫的近 3,000 行代碼。

建構速度是開發者們十分關心的一項名額。在開始處理之前,我覺得移除大量的注解處理器有助于提升建構速度,但我不确定能提升多少。

測試設定

在進行下一步前,很重要的一點是要知道我是如何測量出下面的數字的。我遵循了與 Chris Horner 測量 不同 CPU 上的建構時間 時類似的設定。

我在一台 Lenovo P920 上進行測試,它擁有 192GB RAM 和速度極快的 Xeon Gold 6154 CPU。不用多說,我知道這台機器不是開發者的通常配置,是以為了使測試盡量逼真,我将 CPU 固定在了其最小的時鐘頻率上:

為了準備所有的遠端緩存檔案,接下來我運作了 ./gradlew assembleDebug。

為了執行測試,我循環運作了下列指令五遍:

這裡并不一定需要配置 --max-workers,但這裡如果不設定,Gradle 會使用該 CPU 預設可用的所有 64 個核心。限制到 4 個更接近典型的筆記本電腦 CPU。

結果

您可以在下面看到結果,每個結果都使用了結果報告中的 "總建構時間 (Total Build Time)" 值。

Jetpack Compose 使用前後對比

△ 展示 Tivi 建構時間中位數的圖表

這一結果令我有些驚奇,因為 "完全接入 Compose" 比 "在每個 Fragment 中使用 Compose" 快了 25 秒。

感謝 Ivan Gavrilović 找出原因。這一現象與 Compose 無關。"完全接入 Compose" 使用的是最新版本的 Dagger/Hilt,該版本使用了 Android Gradle Plugin 7.0 中的新 ASM API。而其他版本使用了較舊的 Hilt 版本,其使用了不同的機制,會嚴重拖慢生成 dex 檔案的時間。

退一步講,考慮到 Kotlin 編譯器與 Compose 編譯器插件為我們所做的事情,如位置記憶化、細粒度重組等工作,建構時間能夠 減少 29%, 可以說十分驚人。您可以檢視我們釋出的文章來了解更多:

深入詳解 Jetpack Compose | 優化 UI 建構

深入詳解 Jetpack Compose | 實作原理

關于上面的所有結果,有些事項需要注意:

與新功能相關工作

在這 11 個月中,我沒有在 Tivi 上進行過重大的新功能開發,但我也沒有刻意限制自己。我進行了許多無關乎遷移的修改,可能會使結果産生偏差。

依賴更新

在這 11 個月的遷移過程中,許多依賴都更新了。其中的大多數均為運作時依賴庫,是以最有可能影響 APK 大小這一名額。

我也更新了 Gradle (從 6.0.1 到 7.0.0)、Android Gradle Plugin (3.6.0 到 7.0.0-alpha14) 以及 Kotlin (1.3.61 到 1.4.32),這些更新都可能大幅影響建構速度。

Compose 仍處于 beta 階段

這點是最為顯而易見的。Compose 目前仍處于 beta 階段,是以所有的結果均來自開發過程中一個适時的快照。當今年晚些時候到達 1.0 版時,可以重新運作這些測試,并對比産生了哪些差異。

如果我們看了結果和注意事項,就應該注意到我們并沒有把 ???? 與 ???? 做比較,而更像是在拿 ???? 與比它甜了點的親戚 ???? 進行比較,是以也不應該做出太多評價。

把水果類比放在一邊,我覺得對我來說最大的收獲,是 Compose 對于大多數開發者名額産生的影響是積極 (或中性) 的。考慮到這一點,再加上 Compose 大大提高了開發人員的生産力,對我來說,Compose 無疑是 Android UI 開發的未來。

感謝 Nick Butcher、Jose Alcérreca 和 Jolanda Verhoef。