Gradle更小、更快構(gòu)建APP的奇淫技巧

本文已獲得原作者授權(quán)同意,翻譯以及轉(zhuǎn)載
原文鏈接:Build your Android app Faster and Smaller than ever
作者:Jirawatee
譯文鏈接:Gradle更小、更快構(gòu)建APP的奇淫技巧
翻譯人:MrTrying

Gradle

上個(gè)月,我有機(jī)會(huì)在 LINE DEVELOPER DAY 2018 發(fā)表演講。對(duì)我來(lái)說(shuō)是特殊的時(shí)刻,因?yàn)檫@是我第一次在日本演講。在成為演講者之前,LINE 活動(dòng)的工作人員必須向全球團(tuán)隊(duì)提交他們的演講。

LINE DEVELOPER DAY 2018

我提交的主題是關(guān)于如何更快構(gòu)建 Android App,以及如何生成更小的 APK 的一些技巧。這些提示來(lái)自于我的經(jīng)驗(yàn)和 Google I/O,特別是在 Developer Build Clinic 中收集到的。Developer Build Clinic 是 Android Studio 團(tuán)隊(duì)為改進(jìn)構(gòu)建性能方面提供的一對(duì)一咨詢。

Developer Build Clinic by Android Studio team

在本文中,我想與你分享這些技巧和 app,給你帶來(lái)的 app 是 LINE MAN Driver。

LINE MAN

對(duì)于不知道 LINE MAN 是什么的人來(lái)說(shuō),它是一個(gè)按需助理提供專業(yè)服務(wù)的 app,包括食物配送、便利店貨物配送、信使服務(wù)、包裹服務(wù)和出租車(chē)服務(wù),隨時(shí)滿足所有泰國(guó)用戶的需求。

請(qǐng)注意,實(shí)際結(jié)果可能會(huì)有所不同,因?yàn)樗Q于您的項(xiàng)目特征和構(gòu)建環(huán)境,例如項(xiàng)目規(guī)模、資源、依賴關(guān)系和機(jī)器性能。

構(gòu)建更小App的技巧

APK 的大小將會(huì)影響 app 的加載速度、內(nèi)存占用以及電量消耗。我想大多數(shù)人都知道,APK 大小是用戶參與度的重要因素。讓我們來(lái)看看當(dāng)前在 LINE MAN Driver 中 app 的大小。

當(dāng)前app大小是9MB

優(yōu)化 APK,快速的建議是使用 Android Studio 的APK Analyzer。打開(kāi) Android Studio ,然后選擇Profile or debug APK,瀏覽你的 APK 文件。

APK Analyzer

Tip 1:移除無(wú)用的資源

大多數(shù)人都是在遺留項(xiàng)目中開(kāi)發(fā),有很多圖片、布局和string你從來(lái)沒(méi)有用過(guò),但是你不知道也不想自己刪除它,因?yàn)槟愫ε聲?huì)讓你的 app 崩潰,對(duì)嗎?所以,在 Android Studio 中,它提供了Remove Unused Resources的選項(xiàng)。

它對(duì)我們非常有幫助,因?yàn)樗茏詣?dòng)找到無(wú)用的資源,然后你能一鍵刪除它們。

Tip 2:只添加需要的依賴

有些依賴內(nèi)部包含了一堆庫(kù),像play-servicesFaceBook SDK。如果你沒(méi)有指定你需要的庫(kù),那你將獲得全部的庫(kù),讓你的 app 變胖。例如,如果你想使用
Google 授權(quán),你應(yīng)該指定com.google.android.gms:play-services-auth:16.x.x代替com.google.android.gms:play-services:16.x.x。

你可以通過(guò)下面的命令來(lái)細(xì)分項(xiàng)目的依賴

$ ./gradlew app:dependencies

你將看到在項(xiàng)目中用到的所有的依賴,然后確保只用你所需要的。

Tip 3:為屏幕密度構(gòu)建多個(gè)APK

默認(rèn)情況下,Android Studio 將會(huì)生成一個(gè)包含所有屏幕密度的通用 APK。在此技能中,你能專門(mén)排除或包含你想要在app/build.gradle支持的屏幕密度,Android Studio 將會(huì)為你生成多個(gè) APK。

android {
  splits {
    density {
      enable true
      // Specify a list of screen densities which Gradle won't create multiple APKs for
      exclude 'ldpi', 'mdpi'
      // Specify a list of compatible screen size for the manifest
      compatibleScreens 'small', 'normal', 'large', 'xlarge'
    }
  }
}

所以,你需要將他們所有都上傳到 Google Play,最終你的用戶將會(huì)下載與他們屏幕密度匹配的 APK。

Tip 4:為ABI構(gòu)建多個(gè)APK

這個(gè)技巧和前一個(gè)技巧相似,但是此技巧是用于支持Application Binary Interfaces(ABIs)。今天,我認(rèn)為 Android 市場(chǎng)中有7個(gè) CPU 框架,其中3個(gè)很難找到(mips,mips64armeabi),以此你可以在app/build.gradle指定你想要支持的 ABI,Android Studio 將會(huì)為你生成多個(gè) APK。

android {
  splits {
    abi {
      enable true
      reset()
      // Specify a list of ABIs that Gradle should create APKs for
      include 'x86', 'x86_64', 'arm64-v8a', 'armeabi-v7a'
      // If you don’t want to generate a universal APK that includes all ABIs.
      universalApk false
    }
  }
}

然后,你需要將他們所有都上傳到 Google Play,最后你的用戶將會(huì)下載與他們 CPU 匹配的 APK。

Tip 5:使用特定的ABI構(gòu)建APK

這個(gè)技巧不同于多個(gè) APK。你能指定你想要支持的 CPU 框架,Android Studio 將只生成一個(gè) APK。

android {
  defaultConfig {
    ...
    ndk {
      abiFilters 'x86', 'x86_64', 'arm64-v8a', 'armeabi-v7a'
      // armeabi, mips and mips64 has removed since NDK r17
    }
  }
}

根據(jù)我的經(jīng)驗(yàn),我更喜歡這個(gè)技巧,因?yàn)槲以?jīng)在多個(gè)APK的情況中在某些設(shè)備上發(fā)現(xiàn)了崩潰。

Tip 6:刪除未使用替代資源

有時(shí),你創(chuàng)建一個(gè)本地的 app,你只想支持一些特殊的語(yǔ)言。但是,有一些依賴包含全世界的很多語(yǔ)言,你不需要所有的這些。因此,你可以使用resConfigs屬性指定你想要的語(yǔ)言,你的 app 將更小。

android {
  defaultConfig {
    resConfigs 'en', 'th'
    ...
  }
}

Tip 7:壓縮無(wú)用代碼和資源

默認(rèn)情況下,Android Studio 的 minifyEnabledfalse,但我認(rèn)為很多人為了更小和安全因素把它設(shè)置為true來(lái)縮小和混淆你的代碼。我建議你在app/build.gradle中添加shrinkResources,在壓縮(minify)進(jìn)程之后刪除無(wú)用的資源。因?yàn)樵趬嚎s中,gradle將移除無(wú)用的代碼,這些代碼可能會(huì)引用一些資源。

最后,我想大多數(shù)人都不知道-optimize。你能在proguard-android之后添加-optimize,它將為你構(gòu)建 app 做更多的優(yōu)化,你的 app 將會(huì)更小。

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

請(qǐng)注意,此過(guò)程將花很多時(shí)間,所以你應(yīng)該只在發(fā)布快中使用-optimize。

Tip 8:使用Shape Drawable

有時(shí)候,我看到開(kāi)發(fā)者使用Bitmap的漸變背景或者圓角圖。實(shí)際上,bitmap圖比 Android Studio 提供的Shape Drawable更大,因?yàn)樵?code>Shape Drawable中,你可以以xml的格式繪制矩形、橢圓、圓、圓角和其他。

Tip 9:使用Webp

相同質(zhì)量下 Webp 更小,最多30%。唯一需要注意的是操作系統(tǒng)的要求。如果你使用不透明的背景,Webp 的 API 等級(jí)是API 15及以上支持。但是如果你想在 Webp 中支持透明背景,你需要支持API 18或者更高,Android Studio 還為您提供了一種將圖像轉(zhuǎn)換為 WebP 格式的簡(jiǎn)便方法。你可以右擊你想要的圖片,選擇Convert to WebP,然后你會(huì)看到下圖。

因此,讓我們看一個(gè)示例結(jié)果,圖像尺寸減小到原始尺寸的15%,質(zhì)量為90%。

Tip 10:使用VectorDrawable

API 21起,確保vectorbitmap更小,你能使用vector代替bitmap圖片。因?yàn)?code>VectorDrawable能以相同質(zhì)量的圖,降低大小到不同屏幕密度。

如果你正在支持minSdkVersion 20或者更低。別擔(dān)心,你可以用它。因?yàn)?Android 團(tuán)隊(duì)提供了一個(gè)庫(kù)。因此你只需要使用23.2及其以上支持庫(kù)。

累積改進(jìn)

這是在應(yīng)用這些技巧后所累積的改進(jìn)

還有一件事

從 Android Studeio 3.2 開(kāi)始,Android App Bundle是一種新的 app 發(fā)布格式,可以讓你的 app 小的更輕松。你不需要添加一行代碼,只需要使用新方法導(dǎo)出即可。因此,當(dāng)你下載你的 app 時(shí),Google Play 動(dòng)態(tài)傳輸指定設(shè)備需要的代碼和資源。

通過(guò)這種方式你不需要自己構(gòu)建多個(gè) APK 了。

請(qǐng)注意,文件擴(kuò)展名師.aab,你需要花更多的時(shí)間來(lái)構(gòu)建,但這是值得的。

更快構(gòu)建app的技術(shù)

和 Android 開(kāi)發(fā)者想要改進(jìn)的一樣,構(gòu)建速度對(duì)工作效率至關(guān)重要。從這個(gè)問(wèn)題我有10個(gè)技術(shù)可以更快的構(gòu)建 LINE MAN Driver app。

優(yōu)化之前,我想讓你看看 LINE MAN Driver app 現(xiàn)在在 Android Studio 3.2.1 的完整構(gòu)建速度。

現(xiàn)在構(gòu)建 LINE MAN Driver 的時(shí)間是3分鐘。

Technique 1:使用最新的Android plugin

第一個(gè)技術(shù),確保你的 Android Gradle plugin 是最新的。因?yàn)橛泻芏噱e(cuò)誤修復(fù)和性能問(wèn)題被修復(fù)。

buildscript {
  repositories {
    jcenter()
    google()
  }
  dependencies {
    -  classpath 'com.android.tools.build:gradle:3.0.0'
    + classpath 'com.android.tools.build:gradle:3.2.1'
  }
  ...
}

Technique 2:避免Legacy Multidex

第二個(gè)技術(shù)是避免 Legacy Multidex。如你所知,如果你的 app 超過(guò)64k方法限制,你需要使用 Multidex。如果你的的minSdkVersion是21或更低,你也是用 Multidex,那么你將使用 Legacy Multidex,這會(huì)使你在構(gòu)建時(shí)變慢。

要避免 Legacy Multidex,你可以定義新的flavor,并在app/build.gradle中指定minSdkVersion21或更高。

productFlavors {
  development {
    minSdkVersion 21
    ...
  }
}

Technique 3:禁用Multi APK

第三個(gè)技術(shù),你應(yīng)該在開(kāi)發(fā)構(gòu)建環(huán)境禁用多個(gè) APK 生成,因?yàn)榇虬蛣?chuàng)建這些 APK 需要時(shí)間。所以,你能在app/build.gradle的 debug 代碼塊中添加以下兩行代碼禁用它。

buildTypes {
  ...
  debug {
    splits.abi.enable = false
    splits.density.enable = false
  }
}

Technique 4:包含最少的資源

在你開(kāi)發(fā)構(gòu)建中最小化打包的資源。默認(rèn)情況下,構(gòu)建系統(tǒng)包含 app 和庫(kù)使用的所有語(yǔ)言和屏幕密度。開(kāi)發(fā)期間你不需要用到所有的這些資源,你能通過(guò)添加resConfigs來(lái)使用這些資源中的一組,并指定開(kāi)發(fā)構(gòu)建所需的語(yǔ)言和屏幕密度。

productFlavors {
  dev {
    resConfigs('en', 'xhdpi')
    ...
  }
}

Technique 5:禁用PNG縮緊

默認(rèn)情況AAPT將會(huì)縮進(jìn)PNG來(lái)減小它們的大小,對(duì)于你發(fā)布 APK 是一件好事,但是它對(duì)于你開(kāi)發(fā)構(gòu)建并不重要。要避免PNG縮緊,你可以使用下面的屬性并將其設(shè)置為false。

buildTypes {
  ...
  debug {
    aaptOptions.cruncherEnabled = false
    ...
  }
}

Technipue 6:使用Instant Run

默認(rèn)情況下,當(dāng)你點(diǎn)擊 RUN 按鈕時(shí),系統(tǒng)將會(huì)嘗試?yán)淝袚Q,app 需要重啟,但是當(dāng)你點(diǎn)擊 Apply Changes 按鈕時(shí),系統(tǒng)將先嘗試熱交換,這會(huì)將更改直接推送到實(shí)時(shí)進(jìn)程。

Technipue 7:禁用更新構(gòu)建ID

下一個(gè)技能是在 Firebase Crashlytyics 中禁用更新構(gòu)建ID。我想很多人使用 Crashlytics,每次構(gòu)建 Crashlytics 將默認(rèn)生成一個(gè)唯一的構(gòu)建ID。你可能不知道他們?yōu)槟闾峁┝艘粋€(gè)關(guān)閉它的方式,如下

buildTypes {
  debug {
    ext.alwaysUpdateBuildId = false
    ...
  }
}

你需要注意,只在 debug 塊中設(shè)置為false。

Technipue 8:不要使用動(dòng)態(tài)版本

Gradle 通過(guò)在依賴行末尾添加+,提供一種非常方便獲取每個(gè)依賴的最新版本。它將使 Gradle 每24小時(shí)檢查庫(kù)的新版本,并增加構(gòu)建時(shí)間。

android {
  dependencies {
    implementation 'com.android.support:appcompat-v7:+'
    ...
  }
}

Technipue 9:配置gradle.properties

這里的代碼是我從 Android 開(kāi)發(fā)經(jīng)驗(yàn)中收集的配置。對(duì)我而言,它們就像一種魔法,可以幫助你更快地構(gòu)建 app。

例如,默認(rèn)情況下,Android Studio 會(huì)為你提供1.5GB的內(nèi)存,這可能是好事或壞事,因?yàn)樗鼘?shí)際上取決于你項(xiàng)目的特征。

org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=1024m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

org.gradle.daemon=true

org.gradle.parallel=true

org.gradle.configureondemand=true

org.gradle.caching=true

android.enableBuildScriptClasspathCheck=false

因此,我鼓勵(lì)你嘗試這些配置,我保證你將節(jié)省大量的建設(shè)時(shí)間。

Technipue 10:使用R8新代碼shrinker

下一步是什么?在即將推出的 Android Studio 3.3 中可以使用R8的下一代代碼shrinker。它將減少無(wú)用的代碼和資源,并縮小您的源代碼。因此 Android Studio 聲稱構(gòu)建時(shí)間和 APK 大小會(huì)更小。

image.png

累積改進(jìn)

讓我們看看,在使用這些技巧之后新的完整建筑速度。現(xiàn)在我花了大約1分鐘完成建設(shè)。所以這次累積改進(jìn),完整版本現(xiàn)在快3倍。

總結(jié)

你想象一下,如果你的舊項(xiàng)目比 LINE MAN Driver 程序應(yīng)用程序更大,你可以減少多少大小以及可以節(jié)省多少時(shí)間。

以下是我在 LINE DEVELOPER DAY 2018 的演講中的幻燈片和視頻

所以我希望這些技巧和技巧可以幫助你提高生產(chǎn)力。

Enjoy coding,Thank you!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容