[譯] Android性能最佳實踐:減小您的APK大小看這一篇就夠了

你們都知道開發中應用程序的性能是很是重要的,可是這也是優化提高的難點,本章針對 Android性能實踐——從減小APK的大小開始,提高用戶的體驗。html

原文地址 developer.android.com/topic/perfo…android

本文由 愛學園平臺 進行聯合編輯整理輸出git

原做者:愛學園——莫比烏斯環github

用戶常常會避免下載看起來太大的應用程序,尤爲是在設備鏈接到2G和3G網絡或付費網絡的應用市場內部。這篇文章講述如何減小您的應用程序APK的大小,以便使更多的用戶下載您的應用程序。web

理解APK文件結構

在討論如何下降您的應用程序的大小以前,理解一個應用程序的APK的文件結構它是很是有幫助的。一個APK文件包含一個ZIP歸檔,主要包含您的應用程序的全部文件。這些文件包括Java類文件,資源文件,和包含編譯的文件資源。安全

一個APK包含以下目錄:bash

  • META_INF/:包含CERT.SFCERT.RSK 簽名文件,以及MANIFEST.MF清單文件。
  • assets/:包含應用程序的資產,應用程序可使用一個AssetManager對象檢索。
  • res/:包含不能被編譯進resources.arsc文件的資源。
  • lib/:包含編譯後的代碼,是特定於處理器的軟件層。這個目錄包含爲每一個平臺類型分配的子目錄,像armeabi,armeabi-v7a,arm64-v8a,x86,x86_64,和mips

APK還包含如下文件。其中,只有AndroidManifest.xml是強制性的。服務器

  • resources.arsc:包含編譯的資源。這個文件包含來自文件夾res/values/下全部配置的XML內容。包裝工具提取這個XML內容,將它編譯成二進制形式而且歸檔這些內容。這個內容包括語言字符串和樣式以及路徑下不存在於resources.arsc文件的內容,好比佈局文件和圖片。
  • classes.dex:包含DEX文件中編譯的類能夠被 Dalvik/ART 虛擬機理解的格式。
  • AndroidManifest.xml:包含Android的核心清單文件。這個文件列出了應用的名稱,版本,訪問權限,以及引用的庫文件的應用程序。文件使用Android的二進制XML格式。

減小資源的數量和大小

APK的大小影響應用程序的加載速度,對內存的使用,和它對電量的消耗。一個使您的APK較小的簡單方式是減小它包含資源的數量和大小。特別是,您能夠移除應用程序再也不使用的資源,和您可使用可拉伸的Drawable圖像文件。本節討論這些方法以及其餘幾個方法都是經過減小您的應用程序使用的資源來減小您的APK整體規模。網絡

移除不使用的資源

Android Studio 內部包含一個靜態代碼分析器lint工具,使用它能夠檢索資源文件夾res/,找出您的代碼不引用的資源。當lint工具在您的工程中發現一個潛在的未被使用的資源,它會打印一條消息就像下面的例子。app

res/layout/preferences.xml: Warning: The resource R.layout.preferences appears
    to be unused [UnusedResources]
複製代碼

⚠️:lint工具不能掃描assets/目錄,經過反射引用assets,或您鏈接庫文件到您的應用。同時,它不會刪除資源;只提醒你他們的存在

您的代碼依賴的庫文件或許包含不被使用的資源。若是在您的build.gradle構建文件中啓用shrinkResources,它表示Gradle會自動刪除這些資源。

android {
    // Other settings

    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
複製代碼

爲了使用shrinkResources,你必須啓用代碼壓縮。在構建過程當中,首先ProGuard刪除未被使用的代碼可是閒置未被使用的資源。而後Gradle移除未被使用的資源。

關於ProGuard和其它Android Studio提供的途徑,幫助您減小APK大小的更多的信息,能夠參照Shrink Your Code and Resources

在Android Gradle插件0.7和更高版本上,您能夠聲明您的應用程序支持的配置。Gradle經過使用resConfigresConfigs類別以及默認配置defaultConfig選項,去構建系統。而後構建系統能夠防止不受支持的配置的資源,出如今APK文件中,從而減小APK文件的大小。關於此功能的更多信息,能夠查看 Remove unused alternative resources

最小化來自於外部庫資源的使用

當咱們開發一個Android應用程序時,您一般使用外部庫來提升應用程序的可用性和多功能性。例如,您能夠引用Android Support Library來改善應用程序在舊設備上的用戶體驗,或者您能夠在您的應用程序內部使用Google Play Services來檢索文本,對其進行自動翻譯。

若是一個庫被設計用於一個服務器或桌面。它可能包括許多您的應用程序不須要的對象和方法。爲了作到只包括您須要的部分,若是庫的證書容許您能夠編輯該庫的文件。您還可使用一個替代的方法,移動指定的功能模塊到您的應用程序。

⚠️:ProGuard能夠清除一些沒必要要的代碼導入庫,可是不能移除一個庫龐大的內部依賴關係。

僅僅支持特定密度

Android支持一組很是大的設備,包括各類各樣的屏幕密度。在Android 4.4(API級別19)和更高版本,該框架支持各類密度:ldpimdpitvdpihdpixhdpixxhdpixxxhdpi。即便Android支持全部的這些密度,您也不須要爲每一個密度導出相應的資源。

若是您知道只有一小部分用戶的設備擁有特定的密度,這些密度是否須要包括到您的應用程序中那是值得考慮的。對應於一個特定的屏幕密度,若是您不包括相應的資源,Android會根據其它屏幕密度,找尋與之相近的現有資源。

若是您的應用程序只須要按比例縮小的圖像,在drawable-nodpi/文件下放置惟一圖像便可,這樣您能夠節省更多的空間。咱們建議每個應用程序包括至少一個xxhdpi圖像變體。

關於屏幕密度的更多信息,能夠參見Screen Sizes and Densities

使用drawable對象

一些圖像不要求一個靜態的圖片資源;框架能夠在運行時動態畫出圖像。Drawable對象(<shape>在XML內)在您的APK內部能夠佔用少許的空間。另外,XMLDrawable對象產生的單色圖像符合材料設計(material design)的指導方針。

減小資源

對於一個圖像的變化,您能夠包括一個單獨的資源,如着色、陰影或旋轉版本相同的圖像。無論怎樣,咱們建議您重用相同的一組資源,在運行時根據須要自定義它們。

Android 提供了一些工具來改變資源的顏色,在Android5.0(API21)和更高的版本上可使用android:tint和tintMode屬性。對於較低的平臺版本,可使用ColorFilter類。

對於一種資源通過旋轉能夠獲得另外一種資源,您能夠只導入一個。下面的代碼片斷提供了一個示例:將一個「thumb up」繞軸旋轉180度轉變成「thumb down」:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_thumb_up"
    android:pivotX="50%"
    android:pivotY="50%"
    android:fromDegrees="180" />
複製代碼

圖像經過代碼渲染

您還能夠經過程序渲染您的圖片,進而減小您的APK大小。程序渲染騰出空間,由於您不須要存儲圖片到你的APK文件中。

Crunch PNG 文件

在構建過程當中,aapt工具可使用無損壓縮方式優化放置在res/drawable/目錄下的圖像資源,進而下降圖片空間佔用。例如,the aapt tool can convert a true-color PNG that does not require more than 256 colors to an 8-bit PNG with a color palette(這句很差翻譯).這樣轉換以後,相同質量的圖像會佔用更小的內存。

請注意,aapt擁有如下限制:

  • aapt不能壓縮asset/目錄下的PNG文件。
  • aapt工具優化圖像文件須要使用256或更少的顏色。
  • aapt工具可能屢次優化已經壓縮過的PNG文件。爲了不這個您能夠在Gradle文件中使用cruncherEnabled標誌禁用對PNG文件的處理。
aaptOptions {
    cruncherEnabled = false
}
複製代碼

壓縮 PNG 和 JPEG 文件

您能夠在不丟失圖像質量的狀況下使用工具減小 PNG 文件的大小,像 pngcrush, pngquant, or zopflipng。全部這些工具能夠減小PNG文件的大小,同時保留感知的圖像質量。

pngcrush工具是特別有效的:這個工具遍歷PNG過濾器和zlib(Deflate)參數,使用過濾器和參數的組合壓縮圖像。而後選擇壓縮效果最好的配置輸出(It then chooses the configuration that yields the smallest compressed output)。

爲了壓縮 JPEG 文件,你可使用工具好比: packJPG and guetzli.

使用 WebP 格式文件

針對Android 3.2(API級別13)和更高版本,您還可使用WebP圖像格式文件,而不是使用 PNG 和 JPEG 文件。WebP格式提供了有損壓縮(如JPEG)以及透明度(如PNG),相較於JPEG或PNG它能夠提供更好的壓縮。

使用Android Studio,您能夠轉換存在的 BMP,JPG,PNG 或 靜態的GIF圖像爲 WebP格式。更多的信息,請參考 Create WebP Images Using Android Studio

⚠️:谷歌市場接受APK的啓動圖標只能是PNG格式。

使用矢量圖

您可使用矢量圖形建立分辨率無關圖標和其餘可伸縮的媒體。使用這些圖形能夠大大減小你的APK大小。在Android中,矢量圖表示爲VectorDrawable對象。VectorDrawable對象,一個100字節的文件能夠用於呈現屏幕大小的圖像。

然而,系統須要大量的時間來呈現每一個VectorDrawable對象,且圖像越大呈現到屏幕上所須要的時間越長。所以,考慮只有當顯示小圖像時使用這些矢量圖形。

更多的關於VectorDrawable對象如何工做的信息,能夠參考Working with Drawables

使用矢量圖形動畫圖像

不能使用 AnimationDrawable對象去建立幀動畫,由於這樣作對於每一幀動畫都須要包括一個單獨的bitmap文件,這大大增長APK的大小。

您應該使用AnimatedVectorDrawableCompat去建立矢量動畫

減小 native 和 Java 代碼

這裏有幾種方法能夠用來減小在您的應用程序中 Java 和 native 代碼庫的大小。

移除沒必要要生成的代碼

肯定了解由工具自動生成的任何代碼的足跡(Make sure to understand the footprint of any code which is automatically generated)。例如,許多協議緩衝工具生成過多的方法和類,它可使您的應用程序大小提高兩倍或三倍。

避免使用枚舉

一個枚舉可使您的應用程序的classes.dex文件增長約 1.0 到 1.4 KB大小。對於複雜系統或共享庫這些添加能夠迅速增大此文件。若是可能的話,能夠考慮使用@IntDef註解和ProGuard去剝離枚舉,取出將它們轉換爲整數。這種類型的轉換保存全部的枚舉類型是安全可靠的。

減小本地二進制文件的大小

若是您的應用程序使用本地代碼和Android NDK,你也能夠減小你的應用程序的發佈版本的大小,以優化你的代碼。兩個有用的技術去除調試符號而不是提取本地庫。

移除調試符號

使用調試符號的意義,在於您的應用程序在開發過程當中仍然須要調試。使用arm-eabi-strip工具(Android NDK 提供),從本地庫刪除沒必要要的調試符號。 以後,您能夠編譯發佈構建。

避免提取本地庫

在構建應用程序的發佈版本時,若是您在你的應用程序的清單文件中,元素標籤下設置屬性以下android:extractNativeLibs="false",則APK包將不會壓縮.so文件。禁用這個標誌能夠在應用的安裝過程當中,阻止PackageManager從您的APK拷貝.so文件到文件系統,這樣作的好處是讓您更新您的應用程序更小。

維護多個精簡的 APKS

APK可能包含一些用戶下載但從未使用的內容,如區域或語言信息。爲用戶建立一個最小的下載,你能夠將您的應用程序分割成幾個apk,分化的因素如屏幕大小或GPU硬件的支持。

當用戶下載您的應用程序,他們的設備基於設備的功能和設置接收到正確的APK。這種方式,設備沒有接收到資產設備沒有的功能。例如,若是用戶擁有一個hdpi設備,他們不須要相對於更高密度的設備包括的xxxhdpi資源。

更多相關信息,請參考 Configure APK SplitsMaintaining Multiple APKs

相關文章
相關標籤/搜索