抖音包大小優化-資源優化

1.概述

隨着業務的快速迭代,抖音 Android 端的包大小爆發式增加。包大小直接影響到下載轉化率、推廣成本、運行內存和安裝時間等因素,所以對 apk 進行瘦身是一件頗有必要且收益很大的事情。apk 主要由 dex、resource、asserts、native libraries 和 meta-data 組成,針對每一部分,均可以專項去作包大小優化。
抖音 Android 端通過一段時間努力,包大小優化已經取得了階段性的成果。目前仍在持續的優化中。html

- 優化前 優化後 百分比
抖音 73MB 61.5MB 15.7%
抖音 lite 10MB 4.9MB 51%

其中,資源在 apk 包體積中佔比很大,針對資源進行優化是包大小優化中很重要的部分。本着追求極致的原則,本文將詳細闡述抖音 Android 端針對資源部分的優化措施。android

2.圖片壓縮

2.1 圖片壓縮原理

在不進行壓縮的狀況下,圖片大小計算公式:圖片大小=長 x 寬 x 圖片位深。一張原始圖像(1920x1080),若是每一個像素 32bit 表示(RGBA),那麼圖像須要的存儲大小 1920x1080x4 = 8294400Byte,大約 8M,一張圖這麼大是難以接受的。所以咱們使用的圖片都是通過壓縮的。
圖片壓縮利用的是空間冗餘和視覺冗餘原理:git

  • 空間冗餘利用的是圖像上各採樣點顏色之間存在着的空間連貫性,把本該一個一個像素存儲的數據,合併壓縮存儲,加載時進行解壓還原。一般無損壓縮利用的就是空間冗餘原理。
  • 視覺冗餘是指人類的視覺系統因爲受生理特性的限制,對於圖像場的注意是非均勻的,人對細微的顏色差別感受不明顯。 例如,人類視覺的通常分辨能力爲 26 灰度等級,而通常的圖像的量化採用的是 28 灰度等級,即存在視覺冗餘。 一般有損壓縮利用的是人的視覺冗餘原理,擦除了對人的眼睛來講冗餘的信息。

2.2 優點

抖音 Android 研發團隊開發了 Gradle 插件 McImage,在編譯期間 hook 資源,採用開源的算法 pngquant/guetzli 進行壓縮,支持 webp 壓縮。與 tinypng 等一些已知的方案相比,存在如下優點:github

  • McImage 現支持 webp 壓縮,壓縮比高於 tinypng,不過 Android 上 webp 須要作兼容,下文會詳細介紹;
  • tinypng 不開源,每一個帳號每月只能免費壓縮 500 張;McImage 使用的壓縮算法都是基於開源算法;
  • McImage 不只能夠壓縮 module 中的圖片,還能壓縮 jar 和 aar 中的圖片;
  • McImage 支持壓縮算法擴展,有更優的壓縮算法選擇時擴展方便;
  • 和行業裏其餘方案相比,McImage 還可以支持壓縮包含透明度的 webp 圖片,而且兼容了 aapt2 對資源的 hook。

2.3 收益

McImage 支持兩種優化方式,這兩種優化方式不可同時使用:web

  • Compress,pngquant 壓縮 png 圖片,guetzli 壓縮 jpg 圖片;
  • ConvertWebp,webp 壓縮 png\png 圖片。

webp 的壓縮比要高於 pngquant、guetzli,因此如今更推薦使用 ConvertWebp 這種壓縮方式。算法

McImage 還被應用於字節跳動旗下多個產品的圖片壓縮優化工做中,收益以下:api

描述 收益
抖音-Compress 9.5MB
抖音-ConvertWebp 11.6MB
火山-ConvertWebp 3.6MB
Vigo-ConvertWebp 4MB
Vigo aab-Compress 1.2MB
vigo aab-ConvertWebp 3.2MB
多閃-ConvertWebp 3.5MB

2.4 其餘

除了壓縮、優化圖片,McImage 還提供瞭如下功能:數組

  1. 大圖檢測。在 app/build/mcimage_result 目錄下會生成 mcimage_log.txt 日誌文件,除了輸出轉換結果的日誌外,在最後還輸出了大像素圖片和大致積圖片,閾值可在 McImageConfig 裏進行設置,方便大圖覆盤優化包大小;也支持編譯階段檢測,檢測到大圖直接 block 編譯,可及時發現大圖提交;
  2. 壓縮算法方便擴展。若是想接入其餘壓縮算法,只須要繼承 AbstractTask,實現 ITask 接口中的 work 方法便可;
  3. 支持多線程壓縮。把全部 task 的執行放入線程池中執行,大大縮短了 mcimage 的執行時間;
  4. 增長了圖片緩存 cache,進一步縮短打包時間。在開啓多線程+圖片緩存的狀況下,所有命中緩存的狀況下,整個 mcimage 的過程不到 10s;緩存路徑可配置;
  5. 壓縮質量可配置,知足不一樣的壓縮質量需求,緩存文件也會按照不一樣的壓縮質量進行保存和命中;
  6. 掃描不包含透明通道的圖片到 app/build/mcimage_result 目錄下。

3.webp 無侵入式兼容

3.1 tinypng 和 webp 的選擇

tinypng 與 webp 到底哪一個壓縮比更高呢?在網上找不到兩種壓縮算法壓縮比的直接比較,須要更直觀的對比,因而作了以下的實驗:緩存

  1. 掃描項目中 1960 張圖片,經過不一樣的算法壓縮進行對比:
描述 大小
原圖 13463.07KB
webp 壓縮 4177.18KB
tinypng 壓縮 6732.18KB
  1. 從項目中找 490 張圖片,新建 demo,不一樣算法壓縮圖片後比較打包 apk 的大小:
描述 大小
原圖 APK 9617.53KB
webp 壓縮 APK 3924.06KB
tinypng 壓縮 APK 5386.80KB

經過這兩組實驗對比,能夠看出 webp 的壓縮比是優於 tinypng 的。以前也手動的使用 webp 工具壓縮過抖音工程中全部圖片,包大小減小了 1.6MB 左右。所以選擇了 Webp 壓縮算法。安全

3.2 方案選型

webp 壓縮算法,相較於 pngquant、guetzli、tinypng,webp 壓縮比更高,因此 webbp 壓縮圖片應該是更優的選擇。可是 Android 設備對 webp 的支持存在兼容性問題,在 4.3 以上才徹底支持。經過官網咱們知道,想在應用中直接使用帶有透明度的 webp,minSDK 至少須要是 18。

webp在4.3及以上的設備上才徹底支持

包括抖音、今日頭條在內的頭條系 Android 應用,大部分 minSDK 是 16,沒法直接使用 webp 圖片,須要作低版本兼容。經過大量調研,找到了三種兼容的方式:

- 優勢 缺點
提供特定 api 兼容 實現起來簡單 侵入性太強,必須用特定接口或特定 View 進行加載
LayoutInflater setFactory 進行兼容 實現起來簡單 須要針對全部的 ImageView 及子 View 處理,且必須有統一的 Activity、Fregment 的基類處理
運行時 hook 系統關鍵方法 方法替換,能夠作到無侵入式 實現起來複雜些

3.3 方案實現

想要作到無侵入式的兼容,運行時 hook 不失爲一種最佳的選擇。可是運行時 hook 方案,須要解決如下幾點問題:

  • 選擇的 hook 方案要穩定可靠;
  • hook 點要足夠收斂,保證全部解析圖片的操做都能符合預期。

3.3.1 Hook 方案要穩定可靠

經過對 Xposed、AndFix、Cydia Substrate、dexposed 等常見的 Android Java hook 方案的調研對比,dexposed 具備不須要 root、又能 hook 系統方法的特色,最終選擇 dexposed:

  • dexposed 在 Dalvik 上比較穩定,只須要針對 4.3 如下的手機版本作 hook,不須要考慮版本兼容性問題和系統升級問題;
  • 經過內部數據能夠知道,抖音 4.3 如下的用戶並很少,在十萬級別,佔總用戶數的萬分之幾,風險較低。

3.3.2 Hook 點要足夠收斂

經過閱讀源碼,發現全部圖片被加載解析成 Bitmap 的過程,最終都調用到了 BitmapFactory 中的方法。 好比 ImageView 的 setImageResource() 的調用路徑以下:

ImageView 的 setImageResource 過程,Bitmap 的建立是經過 BitmapFactory 來實現。 如 View 的 setBackgroundResource(int resid)的源碼以下:

查閱全部加載圖片的 api,都會經歷 Resources 調用 getDrawable 的過程。會調用到 Drawable 的相關方法,而後經過 BitmapFactory 去解析不一樣的資源類型(File\ByteArray\Stream\FileDescriptory)爲 Bitmap。由此能夠推斷出,BitmapFactory 是 Android 系統經過不一樣的資源類型加載成 Bitmap 的統一接口,這一點從 BitmapFactory 的類註釋中也能看出:

BitmapFactory註釋

因爲系統加載解析 Bitmap 的過程已經足夠收斂,都是經過 BitmapFactory 來實現,所以 BitmapFactory 是一個很是不錯的 hook 點。

有了穩定的 Hook 方案和足夠收斂的 Hook 點,方案的實現起來就手到擒來了,利用 dexposed 對 BitmapFactory 裏的關鍵方法進行替換就能夠了。

4.多 DPI 優化

Android 爲了適配各類不一樣分辨率或者模式的設備,爲開發者設計了同一資源多個配置的資源路徑,app 經過 resource 獲取圖片資源時,自動根據設備配置加載適配的資源,但這些配置伴隨着的問題就是高分辨率的設備包含低分辨率的無用圖片或者低分辨率的設備包含高分辨率的無用圖片。

通常狀況下,針對國內應用市場,App 爲了減小包大小,會選用市場佔有率最高的一套 dpi(google 推薦 xxhdpi)兼容全部設備。 而針對海外應用市場的 APP,大多會經過 AppBundle 打包上傳至 Google Play,可以享受動態分發 dpi 這一功能,不一樣分辨率手機能夠下載不一樣 dpi 的圖片資源,所以咱們須要提供多套 dpi 來知足全部設備。 在項目中,咱們的圖片有的只有一套 dpi,有的有多套 dpi,針對上述兩種場景,咱們分別在打包時合併資源、複製資源,減小了包大小。

4.1 DPI 複製(bundle 打包)

在國內項目中,爲了減小圖片的佔用,通常都會對市場佔用率高的 dpi 進行適配,好比只保留 xxhdpi 分辨率的圖片。這樣就致使了兩個問題,一個是市場上 2k 分辨率手機愈來愈多,若是之後手機主流分辨率是 xxxhdpi,那麼項目中幾千張圖片修改爲本會很是高。 另外一個問題是,公司很多海外產品是經過 AppBundle 打包上傳到 Google Play 的,可以給不一樣設備用戶下發不一樣 dpi 的資源。但項目中只有 xxhdpi,仍然下發 xxhdpi 的圖片,沒法經過下降 dpi 減少包大小。在巴西,咱們 80%用戶都使用 xhdpi 和 hdpi 手機,xxhdpi 圖片相比 hdpi 佔用多了一倍,這部分收益至關高。

所以,咱們經過壓縮分辨率的方式將高分辨率的圖片下降到低分辨,項目業務只存放最高 dpi 圖片,在打包的時候按需求複製篩選。 咱們在 hook 了圖片壓縮的 task,在圖片壓縮前,獲取到包括依賴庫在內的全部 PNG 圖片,利用 Graphics2D 下降圖片分辨率,放在對應分辨率文件夾中。以後再執行圖片壓縮 task,防止一些圖片重採樣後大小增長。

咱們僅對圖片的分辨率進行縮放,並不下降圖片採樣率,所以在顯示效果上沒有區別。 不一樣 dpi 具體應該調整到多少分辨率,咱們根據 Google 的定義製做了一個表格:

- LDPI MDPI HDPI XHDPI XXHDPI XXXHDPI
分辨率(廣泛) 240x320 320x480 480x800 720x1280 1080x1920 2k
倍率 3 4 6 8 12 16

咱們複製一張 xxhdpi 的默認 logo 到全部 dpi,流程以下圖,xhdpi 和 mdpi 文件夾下沒有對應圖片,複製;在 hdpi 中有對應圖片,跳過;xxxhdpi 也沒有對應圖片,但爲了不下降圖片精度,不能向更高分辨率文件夾複製,跳過。

最終收益如圖,公司內海外產品 TikTok 研發團隊在使用該方案優化時,ldpi 相比 xxhdpi 減小了 2.5M 包大小。同時,低分辨率手機加載圖片時直接加載對應 dpi 圖片資源,再也不須要對高分辨率圖片進行縮放處理,提升了性能。

在複製時須要注意這些問題: 爲了處理包括依賴庫中的全部圖片,在資源合併階段進行了複製,這樣會致使.cache 目錄的不少路徑下會多出大量圖片資源,所以這個插件咱們在 CI 上開啓,避免本地打包新增大量圖片,提交到代碼倉庫。同時,因爲.cache 中被複制了多份圖片,須要在 assemble 打包流程中進行多 dpi 去重。 在 CI 上會有併發場景,同時複製和壓縮會致使.cache 目錄下同時存在 a.png 和 a.webp,出現 Duplicated 錯誤,所以最後須要掃描刪除同名的.png 文件。

4.2 多 DPI 去重(assemble 打包)

針對普通打包模式(直接產出 apk,好比抖音包),咱們能夠選擇只保留一份分辨率偏高的的圖片,這樣高分辨率設備能夠拿到合適的圖片、低分辨率設備經過 Resource 獲取時會自動進行縮放,依然能夠保證合理的運行內存。

多 dpi 圖片能夠經過 Android 自帶的 resConfig 去重,但這個配置只對資源的 qualifier 去重,好比對像素密度和屏幕尺寸不會同時作去重,抖音使用基於 AndResguard 修改的方式對 drawable 去重,能夠定義不一樣配置的優先級和做用範圍。 根據優化配置確保留一份資源,優化方式以下圖(灰色數據表示會被刪除):

5.重複資源合併

隨着項目的迭代,項目中不免會出現相同的資源被重複添加到資源路徑中,對於這類文件,人工處理確定是不可行的,能夠在打包階段自動去重。

抖音選擇在 AndResguard 階段對全部的資源進行分析,對 md5 相同的資源文件保留一份,刪除其他的重複的文件,而後在 AndResguard 寫入 arsc 文件時進行將刪除的資源文件對應的資源路徑指向惟一保留的一份資源文件。 優化方式以下圖:

下圖是抖音 511 版本接入多 dpi 去重與重複資源合併功能的優化結果:


MD5 文件去重

DPI 圖片去重

MD5 文件去重減小文件數量

MD5 文件去重減小文件整體積

DPI 圖片文件去重減小文件數量

DPI 圖片文件去重減小文件整體積

apk 大小

相比於原始包減小

false

false

-

-

-

-

85,030,636

-

true

false

171

156.6KB

-

-

84,883,829

143KB

true

true

171

156.6KB

391

312.9KB

84,507,008

511KB

false

true

-

-

422

434.5KB

84,523,236

495KB

true

true(配置全開)

171

156.6KB

463

465.4KB

84,352,272

662KB

6.shrinkResource 嚴格模式

6.1 背景

隨着項目的開發迭代,咱們會有許多資源已經再也不使用了,但仍然存在於項目中。雖然咱們可使用公司開源的字節碼插件開發平臺 ByteX 開發插件在 ProGuard 以前掃描出一些無用資源,但由於這一步沒有通過無用代碼刪除,所以掃描出的結果並不全。而 shrinkResources 是 google 官方提供的優化此類無用資源的方法,它運行在 Proguard 以後,能標記全部無用資源並將其優化。

6.2 收益

抖音 Android 在開啓 shrinkResources 嚴格模式後,shrink 資源數 600+,收益大小 0.57MB。

6.3 接入方法

shrinkResources 是由 Google 官方提供的工具,所以詳細的接入方式參考 Google Developer 上的文檔便可。

6.4shrinkResources 原理

默認狀況下,Resource shrink 是 safe 模式的,即其會幫助咱們識別相似 val name = String.format("img_%1d", angle + 1) val res = resources.getIdentifier(name, "drawable", packageName) 這樣模式的代碼,從而保證咱們在反射調用資源文件的時候,也是可以安全返回資源的。 從源碼來看,Resource shrink 時會幫助咱們識別如下五種狀況:

而 Resource shrink 使用了一種最笨但卻最安全的方法去獲取匹配的前綴/後綴字符串,那就是將應用中全部的字符串都認爲是可能的前綴/後綴匹配字符串。

因此這就形成了在安全模式下,不當心被某個字符串所匹配到的資源,即便沒有被使用也會被保留下來。以咱們的項目爲例,在 com.ss.android.ugc.aweme.utils.PatternUtils 中,咱們有如下代碼:

在安全模式下,這就形成了全部以 tt 開頭的無用資源都不會被 shrink 掉(這也就是爲何嚴格模式一開,ttlive_ 開頭的無用資源那麼多的緣由)。

而嚴格模式打開後,其做用即是強行關閉這一段的字符匹配的過程:

固然這也就形成了咱們在使用 getIdentifier() 的時候是不安全的,由於嚴格模式下是不會匹配任何字符串的,因此在開啓嚴格模式以後,必定要嚴格檢查全部被 shrink 的資源,是否有本身須要反射的資源!

6.5 shrinkResources 兼容 Dynamic Feature

AppBundle 是 Google 近年來力推的一個功能,它可以讓咱們的 apk 按照不一樣的維度生成下發,也提供了一個動態下發功能的方式,Dynamic Feature。可是若是咱們在開啓 Dynamic Feature 以後使用 shrinkResources,則提示如下錯誤:

由此看來 Google 官方並不支持 App Bundle 使用 Dynamic Feature 時使用 shrink resource。在 Google Issue Tracker 上發現已經有人對此提交過 Issue 了,相關 Issue。而 Google 的回覆也是簡單粗暴----計劃中,可是沒有時間:

可是正常來講,若是作的好的話,咱們的 App Bundle 的 Dynamic Feature 模塊是不多會引用 Master 的資源的,即便有,使用 keep.xml 的方式也能將這種資源給保留下來。所以,理論上來講,單獨對 Master 模塊進行 shrinkResource 並注意反射調用的話,是沒多大問題的。 Dynamic Feature 下檢查 shrinkResources 配置是在 Configuring 階段

所以咱們的想法即是在配置階段不開啓 shrinkResources 開關,而在後面執行資源處理任務的時候自行插入 shrinkResources 的 Task:

這樣就能在 Dynamic Feature 下開啓 shrinkResources 的 Task 了,整個代碼編寫十分簡單,不到 50 行就能完成:

7.資源混淆(兼容 aab 模式)

資源 id 與資源全路徑的映射關係記錄在 arsc 文件中,app 經過資源 id 再經過 Resource 獲取對應的資源,因此對於映射關係中的資源路徑作名字混淆能夠達到減小包體積的效果。

抖音啓用了微信開源的 AndResguard 進行資源混淆,在開源的基礎上進行了增長了 MD5 去、多 DPI 只保留一份資源等優化。 因爲公司內部有不少海外產品,在上架 Google Play 時須要走 aab,所以團隊作了資源混淆的 aab 兼容-- aabResguard,已開源。

8.ARSC 瘦身

8.1 背景

resources.arsc 這個文件在不少項目中都佔用了至關多的空間。常見的優化方法是使用 AndResGuard 混淆減小文件名及目錄長度,7z 壓縮,若是有海外產品的話能夠動態下發語言。 咱們在作完這些優化後,因爲公司內部有不少海外產品,涉及到多語言的關係,ARSC 依然很大,咱們決定嘗試進一步優化。
通過調研,最終咱們對 3 個方面作了優化,分別是刪除無用 Name、合併字符串池中重複字符串、刪除無用文案,最終帶來的收益是 1.6MB。 在此以前,咱們還在 AndResGuard 的基礎上完成了重複 MD5 文件圖片合併,原理是同樣的。

8.2 原理

先貼一張 arsc 結構的圖,這個二進制文件的數據結構至關複雜,AndResGuard 其實只修改了這個文件的一小部分,至於更多的修改就無能爲力了,因而咱們本身解析了這個文件進行分析。 網上也有很多關於這個文件格式的說明,這裏就不贅述了。推薦老羅和尼古拉斯的博客以及 aapt2 源碼。google 提供的 android-arscblamerapktool 的代碼也值得一看。

下面用一張圖簡單描述一下修改過程:

如圖,字符串實際上是經過索引的方式來獲取的,全部字符串都保存在兩個字符串池中(單個 package),一個是全局字符串池,一個是 package 下的字符串池,咱們只須要修改指向全局字符串的偏移值就好了。name 和 value 所在二進制位置以下圖。

8.3 方案

8.3.1 刪除無用 Name

AndResGuard 在今年的 7 月也增長了這個功能,咱們來看一下實現原理。 Name 對應的字符串池是 package 字符串池,因爲這個字符串池中只包含全部 Name,咱們操做能夠稍微暴力一點,先作一份備份,而後清空字符串池,添加一個用於替換的字符串,賦值爲 [name_removed]。

首先要肯定哪些 name 是經過 getIdentifier 調用,配置成白名單。 遍歷 name 項,若是不在白名單,那麼把這一個 name 的偏移替換成 0,使其指向[name_removed]。 若是 name 在白名單,那麼不該該刪除,咱們經過備份的字符串池找到這個 name 對應的字符串,添加到字符串池中,把偏移指向對應下標便可。

抖音經過這個優化減小了包大小 70k。

8.3.2 合併重複字符串

value 所對應的是全局字符串池,雖然名字聽起來不會有重複值,但在咱們掃描排序後發現其實有不少重複字符串(用 AppBundle 打包就不會存在這個問題) 在抖音項目中,這個字符串池裏有 1k+個重複字符串,合併這些字符串是很是必要的。

咱們先遍歷全部數據,而後把字符串池的重複字符串合併,記錄偏移的修改,最後把須要修改的 value 的引用指向新的偏移。這個過程須要操做 arsc 數據結構的 ResValuel 和 ResTableMap,以保證全部 string 類型的值都能獲得替換。

抖音經過這個優化減小了包大小 30k。

8.3.3 刪除無用文案

在打包過程當中,其實全部 strings.xml 中保存的字符串都是不會被優化的,隨着項目逐漸變大,一些廢棄文案或者下個版本纔有用的文案被引入了 apk 中,咱們在 Proguard 後再次掃描,發現了 3000+個無用字符串。在公司內部的一些海外項目中,有的文案被翻譯成 100 多個國家的語言,佔用了極大的空間。

刪除的方法和上面相似,都是指向替換的字符串所在偏移。 如圖可能會存在兩個不一樣 name 指向同一個字符串,須要判斷待刪除的字符串是否還有其餘引用。

不一樣項目收益可能不太同樣,公司內部海外項目對這些無用文案進行了替換,減小了 1.5M 包大小左右。

8.4 實現

若是是普通的 assemble 打包,直接在 ProcessResources 過程當中獲取 ap_文件中的 arsc 文件,利用咱們的工具修改便可。

若是是 AppBundle 方式打包,修改 ap_是沒有用的,由於最後產物是用 aapt 以 proto 格式生成的 resources.pb 文件,要修改只能 hook aapt 過程。這個文件和 arsc 文件結構不太同樣,好在咱們可使用官方提供的 Resources 類解析、生成 pb 文件,使用類似的方法修改便可。

修改效果如圖:

8.5 進一步優化

arsc 中的偏移數組是有優化空間的,咱們會在將來嘗試進行優化。 用二進制編輯器打開 arsc 文件能夠發現,這樣的 FF 值在文件中大量存在。

是什麼致使了這樣的空間浪費? 咱們能夠看到下圖中框選的空白,每個都表明了其字符串所在的偏移值,這裏並無值,賦值 FF FF FF FF 做爲默認偏移值,浪費了 4 字節空間。 某些列(configuration)可能就只有幾個格子有值,如圖抖音中 drawable 有 4k+張圖片,有 24 列,大多數 configuration 只有幾張圖片,所以浪費了 4k*23*4≈380k。大體估算,抖音能夠減小 1M 體積。(壓縮前)

以下圖 facebook 針對 arsc 文件的處理,咱們能夠把一行只有一個值的 id 抽出來,單獨放到一個 Resource Type 中,每個 id 只有一個值,避免了上述空間浪費狀況。 但這樣作修改了 ID,所以對應的代碼中的 ID 也要修改,涉及了逆向 xml 以及 dex,提升了修改爲本。還有一種思路是修改 aapt 源碼,沒有直接改 arsc 靈活。

9.總結

上述就是咱們抖音 Android 端在包大小優化方面針對資源作的一些嘗試和積累,力求追求極致。

咱們針對包大小優化,在其餘方面還作了不少優化措施:針對 so 優化,作了 so 合併、stl 版本統1、精簡導出符號表和 so 壓縮等措施;針對代碼優化,細化混淆規則,開發 bytex 插件進行無用代碼掃描、acess 方法內聯、getter/setter 方法內聯、刪除行號等優化措施。

除了優化措施,良好的包大小監控系統是防止包大小劣化最重要的工具,不然包大小優化措施取得的收益抵不過業務快速迭代帶來的包大小增加。抖音 Android 端結合 CI、Cony 平臺,開發出了一套代碼合入前置檢查系統,每一個分支增量超過閾值不許合入;還開發了分業務線監控包大小的工具,便於監控每一個業務線包大小增加和給各個業務線定包大小指標。

最後,抖音 Android 誠招對技術有無限熱情的小夥伴。感興趣的小夥伴均可以經過 字節跳動招聘官網查詢抖音 Android 相關職位 或簡歷發送至 shipeiqing@bytedance.com

更多分享

抖音BoostMultiDex優化實踐:Android低版本上APP首次啓動時間減小80%(二)

抖音BoostMultiDex優化實踐:Android低版本上APP首次啓動時間減小80%(一)

開源 | AabResGuard: AAB 資源混淆工具

歡迎關注字節跳動技術團隊

相關文章
相關標籤/搜索