Android性能優(yōu)化之APK瘦身詳解(瘦身73%)

公司項(xiàng)目在不斷的改版迭代中构捡,代碼在不斷的累加液南,終于apk包不負(fù)重負(fù)了,已經(jīng)到了八十多M了勾徽』梗可能要換種方式表達(dá),到目前為止沒(méi)有正真的往外推過(guò)喘帚,一直在內(nèi)部執(zhí)行7天討論需求畅姊,5天代碼實(shí)現(xiàn)的階段。你在寫(xiě)上個(gè)版本的內(nèi)容吹由,好了若未,下個(gè)版本的更新內(nèi)容已經(jīng)定稿了∏泠辏基于這種快速開(kāi)發(fā)的現(xiàn)狀粗合,我們app優(yōu)化前已經(jīng)有87.1M了,包大了乌昔,運(yùn)營(yíng)說(shuō)這樣轉(zhuǎn)化不高隙疚,只能好好搞一下咯。優(yōu)化過(guò)后包大小為23.1M(優(yōu)化了73%,不要說(shuō)我標(biāo)題黨)磕道。好了好了供屉,我要闡述我的apk超級(jí)無(wú)敵魔鬼瘦身之心得了。

文章主要內(nèi)容從理論出發(fā),再做實(shí)際操作伶丐。分為下面幾個(gè)方面:1. 結(jié)構(gòu)分析悼做, 2.具體實(shí)操 3. 總結(jié) 4. 參考資料

1. 結(jié)構(gòu)分析

首先上傳一張瘦身前通過(guò)Analyze app分析出來(lái)的圖片(打開(kāi)方式:Android Studio下 ——> Build——> Analyze app):

APK包結(jié)構(gòu)如下:

  1. lib/:包含特定于處理器軟件層的編譯代碼。該目錄包含了每種平臺(tái)的子目錄撵割,像armeabi贿堰,armeabi-v7a, arm64-v8a啡彬,x86羹与,x86_64,和mips庶灿。大多數(shù)情況下我們可以只用一種armeabi-v7a纵搁,后面會(huì)講到原因。
  2. assets/:包含應(yīng)用可以使用AssetManager對(duì)象檢索的應(yīng)用資源往踢。
  3. res/:包含未編譯到的資源 resources.arsc,主要有圖片資源文件腾誉。
  4. META-INF/:包含CERT.SF和 CERT.RSA簽名文件以及MANIFEST.MF 清單文件。
  5. resources.arsc:包含已編譯的資源峻呕。該文件包含res/values/ 文件夾所有配置中的XML內(nèi)容利职。打包工具提取此XML內(nèi)容,將其編譯為二進(jìn)制格式瘦癌,并將內(nèi)容歸檔猪贪。此內(nèi)容包括語(yǔ)言字符串和樣式,以及直接包含在resources.arsc文件中的內(nèi)容路徑 讯私,例如布局文件和圖像热押。
  6. classes.dex:包含以Dalvik / ART虛擬機(jī)可理解的DEX文件格式編譯的類。
  7. AndroidManifest.xml:包含核心Android清單文件斤寇。該文件列出應(yīng)用程序的名稱桶癣,版本,訪問(wèn)權(quán)限和引用的庫(kù)文件娘锁。該文件使用Android的二進(jìn)制XML格式牙寞。

通過(guò)分析圖可以知道,目前app主要是so文件占比比較大莫秆,占了31.7M,占了整個(gè)應(yīng)用是38.2%碎税。其次是assets目錄,整個(gè)目錄占了32M,第三就是資源文件res目錄了馏锡。所以接下來(lái)我們處理步驟就是按這個(gè)順序來(lái)處理雷蹂。(簡(jiǎn)單說(shuō)下圖中的Raw File Size(磁盤解壓后的大小)和DownLoad Size(從應(yīng)用商店下載的大斜馈)匪煌,如果想了解更多關(guān)于Analyaer分析的知識(shí)责蝠,可以參考這篇文章使用APK Analyzer分析你的APK),分析了包結(jié)構(gòu)組成之后萎庭,我們可以開(kāi)始瘦身操作了霜医。

2.具體實(shí)操

1. 對(duì)lib目錄下的文件進(jìn)行瘦身處理

1. 修改lib配置:

參考資料
so文件的優(yōu)化:通常我們?cè)谑褂肗DK開(kāi)發(fā)的時(shí)候,我們經(jīng)常會(huì)有如下這么一段代碼:

ndk {
            //設(shè)置支持的so庫(kù)架構(gòu)
            abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64", "armeabi"
        }

最后我的修改代碼如下:

ndk     {
            //設(shè)置支持的so庫(kù)架構(gòu)
            abiFilters "armeabi-v7a"
        }

接下來(lái)說(shuō)明這么做的依據(jù):
看上面圖分析驳规,armeabi-v7主要不支持ARMv5(1998年誕生)和ARMv6(2001年誕生).目前這兩款處理器的手機(jī)設(shè)備基本不在我公司的適配范圍(市場(chǎng)占比太少)肴敛。
而許多基于 x86 的設(shè)備也可運(yùn)行 armeabi-v7a 和 armeabi NDK 二進(jìn)制文件。對(duì)于這些設(shè)備吗购,主要 ABI 將是 x86医男,輔助 ABI 是 armeabi-v7a。
最后總結(jié)一點(diǎn):如果適配版本高于4.1版本捻勉,可以直接像我上面這樣寫(xiě)镀梭,當(dāng)然,如果armeabi-v7a不是設(shè)備主要ABI踱启,那么會(huì)在性能上造成一定的影響报账。
參考文章:安卓app打包的時(shí)候還需要兼容armeabi么?

好了埠偿,我們?cè)俅蛞淮伟囋嚒?/p>


確實(shí)有點(diǎn)震驚透罢,一下子包小了這么多,從87.1M到51.9M,容我好好算算少了多少M(fèi).趕快讓測(cè)試幫忙測(cè)一下冠蒋∮鹌裕基于之前的理論知識(shí),心里還是有點(diǎn)底浊服。果然统屈,測(cè)試效果和之前是一樣的胚吁。心里的石頭先落下羅牙躺。

2. 重新編譯so文件,用更小的庫(kù)代替

相信很多開(kāi)發(fā)者都有這種苦惱腕扶,很多第三方我們導(dǎo)入進(jìn)來(lái)只用到其中很小一部分功能孽拷,大部分功能都是我們用不上的。這時(shí)候我們找到源代碼半抱,將我們需要的那部分代碼提取出來(lái)脓恕,重新編譯成新的so文件,再導(dǎo)入到我們項(xiàng)目中窿侈。當(dāng)然炼幔,如果之前沒(méi)有編譯過(guò)so文件,這部分建議做最后的優(yōu)化去處理史简。不然你會(huì)遇到很多問(wèn)題乃秀。上一波處理后的效果圖:


這里說(shuō)下,因?yàn)轫?xiàng)目中有使用到ffmpeg庫(kù),之前導(dǎo)入的第三方的放在assets文件夾下跺讯,重寫(xiě)編寫(xiě)后的so庫(kù)文件放在lib文件夾下枢贿,所以lib文件夾反而大了。從51.9M到35.6M,效果還是蠻不錯(cuò)的刀脏。

對(duì)了局荚,別問(wèn)我為什么assets文件夾下為什么還有12.6M資源,因?yàn)楹芏?mp3都是第三方的人臉識(shí)別必備配置文件愈污,我也很無(wú)奈耀态。

2. 優(yōu)化res,assets文件大小

1. 手動(dòng)lint檢查,手動(dòng)刪除無(wú)用資源

在Android Studio中打開(kāi)“Analyze” 然后選擇"Inspect Code..."钙畔,范圍選擇整個(gè)項(xiàng)目茫陆,然后點(diǎn)擊"OK"。配置如下:

2. 使用tinypng等圖片壓縮工具對(duì)圖片進(jìn)行壓縮擎析。

打開(kāi)網(wǎng)址簿盅,將大圖片導(dǎo)入到tinypng,替換之前的圖片資源揍魂。

3. 大部分圖片使用Webp格式代替桨醋。

可以給UI提要求,讓他們將圖片資源設(shè)置為Webp格式现斋,這樣的話圖片資源會(huì)小很多喜最。如果想了解更多關(guān)于webp,請(qǐng)點(diǎn)擊這里webp,當(dāng)然庄蹋,如果對(duì)圖片顏色通道要求不高瞬内,可以考慮轉(zhuǎn)jpg,最好用webp,因?yàn)樾Ч选?/p>

4. 盡量不要在項(xiàng)目中使用幀動(dòng)畫(huà)

一個(gè)幀動(dòng)畫(huà)幾十張圖片,再怎么壓縮都還是占很大內(nèi)存比重的限书。所以建議是讓UI去搞虫蝶,這里可以參考使用lottie-android,如果項(xiàng)目中動(dòng)畫(huà)效果多的話效果更加明顯倦西。當(dāng)然這就要辛苦我們UI設(shè)計(jì)師大大了能真。

5. 使用gradle開(kāi)啟shrinkResources

移除無(wú)用資源文件,下面是我的配置:

 buildTypes {
        release {
            // 不顯示Log
            buildConfigField "boolean", "LOG_DEBUG", "false"
            //混淆
            minifyEnabled true
            // 移除無(wú)用的resource文件
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
    }

通過(guò)上述步驟操作扰柠,apk效果如下:

又優(yōu)化了將近5M,別問(wèn)我為什么還有7.5M粉铐,里面大量的gif和webp格式的動(dòng)圖,都是UI丟給我的卤档,一個(gè)2.7M.后面再慢慢和他細(xì)究這個(gè)問(wèn)題蝙泼。后面要做的兩部分,一部分是將資源文件下的所有g(shù)if圖放后臺(tái)下載處理劝枣,第二個(gè)是和UI討論下如何減小webp 動(dòng)圖的大刑捞ぁ(我看其他平臺(tái)只有100K的樣子倡缠,給我的就2.7M?)。

3. 減少chasses.dex大小

classes.dex中包含了所有的java代碼茎活,當(dāng)你打包時(shí)昙沦,gradle會(huì)將所有模板力的.class文件轉(zhuǎn)換成classes.dex文件,當(dāng)然载荔,如果方法數(shù)超過(guò)64K盾饮,將要新增其他文件進(jìn)行存儲(chǔ)±廖酰可以通過(guò)multidexing分多個(gè)文件丘损,比如我這里的chasses2.dex。換句話說(shuō)工扎,就是減少代碼量徘钥。我們可以通過(guò)以下方法來(lái)實(shí)現(xiàn):

  1. 盡量減少第三方庫(kù)的引用,這個(gè)在上面我們已經(jīng)做過(guò)優(yōu)化了肢娘。
  2. 避免使用枚舉呈础,這里特別去網(wǎng)上查了一下,具體可以參考下這篇文章Android 中的 Enum 到底占多少內(nèi)存橱健?該如何用而钞?,得出的結(jié)論是拘荡,可能幾十個(gè)枚舉的內(nèi)存占有量才相當(dāng)一張圖片這樣子臼节,優(yōu)化效果也不會(huì)特別明顯。當(dāng)然珊皿,如果你是個(gè)追求極致的人网缝,我不反對(duì)你用靜態(tài)常量替代枚舉。
  3. 如果你的dex文件太大蟋定,檢查是否引入了重復(fù)功能的第三方庫(kù)(圖片加載庫(kù)粉臊,glide,picasso,fresco,image_loader,如果不是你一個(gè)人單獨(dú)開(kāi)發(fā)完成的很容易出現(xiàn)這種情況)溢吻,盡量做到一個(gè)功能點(diǎn)一個(gè)庫(kù)解決维费。

關(guān)于classes.dex文件大小分析可以參考這篇譯文使用 APK Analyzer 分析你的 APK

4. 其他

  1. 用7zip代替壓縮資源果元。
  2. 刪除翻譯資源促王,只保留中英文
  3. 嘗試將andorid support庫(kù)徹底踢出你的項(xiàng)目。
  4. 嘗試使用動(dòng)態(tài)加載so庫(kù)文件而晒,插件化開(kāi)發(fā)蝇狼。
  5. 將大資源文件放到服務(wù)端,啟動(dòng)后自動(dòng)下載使用倡怎。

3. 總結(jié)

好了迅耘,說(shuō)道這里基本上就結(jié)束了贱枣,apk包從87.1M減小到了23.1M(優(yōu)化了73%,不要說(shuō)我標(biāo)題黨)已經(jīng)差不多了,關(guān)于第四部其他部分的優(yōu)化我是沒(méi)有進(jìn)行再操作的颤专。因?yàn)楣具\(yùn)營(yíng)覺(jué)得二三十M的包比較真實(shí)纽哥,太小了就太假了。所以我暫時(shí)就不進(jìn)行優(yōu)化了栖秕。如果再上面提到的部分通過(guò)所有將所有非啟動(dòng)頁(yè)面首頁(yè)之外的所有資源春塌,so庫(kù)放服務(wù)端,理論上apk包大小能在10M以內(nèi)這樣子簇捍。當(dāng)然我們有做到就不多加評(píng)價(jià)了只壳。最后,如果對(duì)插件化開(kāi)發(fā)感興趣的話可以參考下這篇文章Android全面插件化方案-RePlugin踩坑暑塑。最后吼句,如果你在Android上有什么疑問(wèn),可以添加我的同名微信公眾號(hào)aserbao和我一塊交流事格。

個(gè)人微信 公眾號(hào) 微信交流群過(guò)期請(qǐng)點(diǎn)擊這里

文章本來(lái)是周三的差不多的惕艳,到今天才發(fā),還是有點(diǎn)小偷懶了驹愚。最后祝大家五一快樂(lè)尔艇,出門玩的開(kāi)心。如果你看到了這里么鹤,覺(jué)得文章寫(xiě)得不錯(cuò)就給個(gè)贊唄终娃?如果你覺(jué)得那里值得改進(jìn)的,請(qǐng)給我留言蒸甜。一定會(huì)認(rèn)真查詢棠耕,修正不足。謝謝柠新。


這里寫(xiě)圖片描述

4. 參考資料:

文章主要參考文章如下窍荧,文章有少部分文字參考了下面文章中的語(yǔ)句。如果有侵犯到作者權(quán)益恨憎,請(qǐng)和我聯(lián)系蕊退,查實(shí)后馬上刪除。

  1. Android APK 瘦身 - JOOX Music項(xiàng)目實(shí)戰(zhàn)
  2. APK 瘦身記憔恳,如何實(shí)現(xiàn)高達(dá) 53% 的壓縮效果
  3. 使用APK Analyzer分析你的APK
  4. 安卓app打包的時(shí)候還需要兼容armeabi么瓤荔?
  5. 百度百科webp
  6. Android 中的 Enum 到底占多少內(nèi)存?該如何用钥组?

推薦閱讀:Android性能優(yōu)化之內(nèi)存泄漏無(wú)處可藏(圖文)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末输硝,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子程梦,更是在濱河造成了極大的恐慌点把,老刑警劉巖橘荠,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異郎逃,居然都是意外死亡哥童,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門褒翰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)如蚜,“玉大人,你說(shuō)我怎么就攤上這事影暴〈戆睿” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵型宙,是天一觀的道長(zhǎng)撬呢。 經(jīng)常有香客問(wèn)我,道長(zhǎng)妆兑,這世上最難降的妖魔是什么魂拦? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮搁嗓,結(jié)果婚禮上芯勘,老公的妹妹穿的比我還像新娘。我一直安慰自己腺逛,他們只是感情好荷愕,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著棍矛,像睡著了一般安疗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上够委,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天荐类,我揣著相機(jī)與錄音,去河邊找鬼茁帽。 笑死禁熏,一個(gè)胖子當(dāng)著我的面吹牛旁壮,可吹牛的內(nèi)容都是我干的圆米。 我是一名探鬼主播蹦魔,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼战秋!你這毒婦竟也來(lái)了璧亚?” 一聲冷哼從身側(cè)響起讨韭,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤脂信,失蹤者是張志新(化名)和其女友劉穎癣蟋,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體狰闪,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡疯搅,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了埋泵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片幔欧。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖丽声,靈堂內(nèi)的尸體忽然破棺而出礁蔗,到底是詐尸還是另有隱情,我是刑警寧澤雁社,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布浴井,位于F島的核電站,受9級(jí)特大地震影響霉撵,放射性物質(zhì)發(fā)生泄漏磺浙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一徒坡、第九天 我趴在偏房一處隱蔽的房頂上張望撕氧。 院中可真熱鬧,春花似錦喇完、人聲如沸伦泥。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)奄喂。三九已至,卻和暖如春海洼,著一層夾襖步出監(jiān)牢的瞬間跨新,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工坏逢, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留域帐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓是整,卻偏偏與公主長(zhǎng)得像肖揣,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子浮入,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容