Readhub+ 發佈後,後臺有人留言要源碼的,還有人問 Apk 怎麼壓縮的。可是目前還不打算開源,因此沒有源碼。不過卻是能夠分享一下我在壓縮 Readhub+ Apk 的一點小小的心得。android
關於 Apk的壓縮與優化,這是一個老生常談的話題了。你們耳熟能詳的方法就有不少,好比開啓混淆,壓縮圖片,使用 SVG,去除無用庫,使用 AndResGuard 之類的。這些網上已經有太多教程了,我就再也不贅述了。今天這篇文章,是想和你們分享下不那麼耳熟能詳的思路。git
幾年前,我也寫過一篇關於 Apk壓縮的文章,當時老闆說要推廣應用,爲了方便用戶下載,叫我把 Apk 弄小點,畢竟當時流量費仍是挺貴的。最開始通過上面提到的那些操做後,安裝包只減小了 1M 左右,優化效果並不明顯,由於寫代碼的時候已經比較注意規範了,因此常規的優化操做效果有限。github
後來,通過仔細分析了 Apk 的組成後,我發現有一個層級比較深的頁面用到了地圖,由於地圖會引入 so 文件,就會致使 Apk 體積增長不少。因此我很機(ji)智(zei)的用 js 地圖代替了原生地圖,一會兒 Apk 就只剩下 3M多了,這是當時那篇文章,《Android快速實現地圖功能(不只快!並且小!)》,感興趣的能夠去看下。固然,這種作法如今已經很廣泛了。bash
我以爲 Apk 優化,在代碼自己已經寫的比較規範的狀況下,常規的壓縮操做帶來的效果是很是有限的。若是想要作到極限壓縮,那就必定要用一些"很是手段",這不只要從技術層面考慮,還要結合產品自身的特色。好比產品針對的用戶羣體,產品面向的市場範圍等。工具
拿我最近發佈的 Readhub+ App來講:gradle
- v1.0.0 版本,Apk 大小 1.14M
- v1.2.0 版本,Apk 大小 1.13M
- v1.5.0 版本,Apk 大小 861K
- v1.8.0 版本,Apk 大小 858.25K
功能雖然在一直增長,但安裝包卻在一直在減少。並且若是要較真的話,這仍然稱不上是極限狀態,由於項目中仍是用到了不少三方庫,若是把這些庫都去掉的話,可能最終只有不到 500K 的樣子。不過 800K 相較於如今動不動就好幾十兆的 App 來講,簡直已是能夠忽略的大小了,因此也就不打算繼續在這上面耗時間了。優化
既然提到了,就順便說一下吧,Readhub+ 的 v1.8.0 版本也發佈了,加入了不少設置功能,因爲這個不是本文主要內容,就不具體說了,我把更新日誌單獨寫到了一篇文章裏,須要的朋友能夠到公衆號看《 Readhub+ 更新日誌》。網站
再說回到 Readhub+ Apk 的優化上,其實說實話,我以爲也沒什麼太有技術含量的操做,可能只不過是你壓根沒往那個方面想而已。並且這個也要結合項目自身的特色,因此這篇文章更多的是但願提供一個思路而已。ui
爲了在 v1.2.0 的基礎上,繼續減少 Apk 的體積,我用 Android Studio 自帶的工具分析了 Apk 文件的組成。以下圖所示,其中 support 包就佔了很大的體積,可是包中大部分的組件我都沒有用到,雖然已經開啓了混淆,可是再怎麼混淆,也只是減少了文件的大小,並無徹底去除文件。google
因而我就想着能不能把 support 包中無用的文件去掉。開始想經過編譯的手段實現,在網上搜了一圈後,發現 gradle 目前好像不具有排除 jar 包中指定類的能力,並且即使有,那也是一個巨大的工程了。因此只能經過笨辦法了,拷貝 support 包中的源碼。在以前的項目中,已經默認習慣了引入 v4 包和 v7 包,因此開始優化 Apk 的時候也壓根沒有朝這個方面想。
正如我剛開始所說,思路仍是很簡單的。但比較奇怪的是,當我搜索網上關於 Apk 優化的文章時,幾乎沒有哪篇提到這種作法的,也不知道是否是由於這種作法太 low 了,簡直讓不少人難以啓齒?仍是這壓根都不能算個方法?
但儘管拷貝聽起來很「無腦」,可我以爲對於沒有這樣作過的人來講,仍是很容易走一些彎路的。由於我在拷貝的過程當中,就遇到了一些問題。(確定有人心想,連代碼拷貝都能出問題?真「辣雞」,啼笑皆非.jpg)
。由於 support 包中代碼很是多,因此拷貝哪一個版本,拷貝哪些文件,怎麼拷貝都算是問題。
4.1 拷貝哪一個版本
Readhub+ 拷貝的是 androidx 中的代碼,由於相較於 27.0.0 和 28.0.0,甚至更早版本的 support 包來講,谷歌對 androidx 的包結構作了更加細化的區分,並且將不少 Material Design View 類組件都拆分到了一個單獨的 material-components 開源倉庫中,這樣拷貝起來也就更加方便了。
4.2 怎麼拷貝
在操做過程當中,我發現拷代碼實際上是比較簡單的,比較麻煩的是拷貝 support 包中各類 res 資源,不過這裏有兩種作法能夠減小一些工做量。第一種是經過在 gradle 設置 sourceSets 屬性,將不一樣包中的 res 資源區分開。第二種就是新建一個Android Module 專門用來放 support 包中的各類 res 文件。這樣就不會和本身項目中的資源混起來了,後期管理和維護起來也比較方便,Readhub+ 就是用的這種方式。
4.3 拷貝哪些文件
這個就有點因人而異了,應該說是因項目而已了,若是你追求極致的小,那麼儘可能不要拷貝 View 類的組件了,想要什麼效果能夠本身手寫一個。由於 support 包的 View 組件,不少都考慮了兼容問題,因此有不少代碼都是爲了提升對低版本的兼容性而寫的。這可能對於大家的項目來講是徹底多餘的。
可能有些人會有疑問,這麼直接拷貝代碼,不利於後期的升級維護啊。這個我以爲大可放心,首先 support 包的升級頻率是很是低的,加上咱們拷貝的是穩定版中的代碼,除非出現了致命性的 bug,否則就算不升級通常也不會有什麼問題。
經過一通拷貝以後,Readhub+ 中 support 代碼佔用的體積減小了 46.7%,一下就減小了好幾百K,這對於一個自己只有 1.2M 的應用來講,已是至關大的瘦身了,簡直就是從賈玲瘦成了林志玲!
經過拷貝 support 包的代碼,已經讓 Apk 的體積小了很多,但仍是有繼續優化的空間的。這就又要提到文章開頭說的,須要咱們要結合產品自身的特色,進行一些定向的優化了。
好比產品的定位,投放的市場,針對的用戶等。若是產品只投放到國內市場,那麼咱們能夠在 gradle 中配置只保留 zh 這部分語言資源,這也能夠減少十幾 K的大小;還有,若是咱們針對的是比較年輕的用戶,那麼在適配分辨率的時候,能夠只考慮 xxhdpi 以上的設備,甚至連 logo 也能夠只保留一套,在 Readhub+ 中就是這樣作的。
splits {
density {
enable true
exclude "mdpi", "ldpi", "hdpi", "xhdpi", "xxxhdpi"
compatibleScreens 'small', 'normal', 'large', 'xlarge'
}
}
複製代碼
固然,還有一些其餘方式,這個就和項目自己有很大的關聯了,因此這裏也只能提供一個思路而已。仍是文章開頭那句話,若是你真的想讓你的 Apk 變得很是小,那就必定要結合項目自身的特色去分析,看哪裏還能減少體積的。
雖而後面這些操做減小的體積並很少,只有幾十 K 的樣子,但這是在Readhub+ 僅有 800 多 K 的基礎上減少了這麼多。在這個體積下,哪怕每減少 1K也都是挺不容易的了。
最後,文章看完了,可能有些人比較懵逼,我在文中反覆提到的 Readhub+ App是個什麼應用?這是我最近發佈到酷安市場的一款三方Readhub 客戶端,至於 Readhub 又是幹嗎的?簡單點說就是個高效獲取新聞的網站,感興趣的能夠本身百度下。至於應用下載,能夠在我公衆號對話窗口回覆:Readhub 獲取。
相關資源:
推薦閱讀: