[TOC]
gradle 任務(wù)優(yōu)化
gradle 是基于 tasks 的,每個(gè)task作為一個(gè)構(gòu)建耗時(shí)單元,task就是構(gòu)建優(yōu)化的單元
gradle 編譯優(yōu)化就是對(duì)
- 構(gòu)建鏈的task組合方式
- 鏈上節(jié)點(diǎn)task耗時(shí)優(yōu)化
- 鏈上節(jié)點(diǎn)task性能優(yōu)化
查看任務(wù)
# 查看某個(gè)模塊的任務(wù)
./gradlew :[moduleName]:task
# 等效
./gradlew :[moduleName]:tasks
# 查看所有任務(wù)
./gradlew tasks --all
查看當(dāng)前構(gòu)建耗時(shí)
./gradlew [task] --profile
在工程的根目錄的 build/reports/profile/
下有最新一次構(gòu)建的耗時(shí)統(tǒng)計(jì)
針對(duì)不同的耗時(shí)問題,可以對(duì)構(gòu)建需要優(yōu)化的 task 進(jìn)行優(yōu)化
輸入獨(dú)立產(chǎn)品線,構(gòu)建類型
gradle :[moduleName]:assemble[產(chǎn)品線][構(gòu)建類型]
./gradlew :app:assembleTestDebug
./gradlew :app:assembleTestRelease
多產(chǎn)品線 productFlavors 使用后,會(huì)明顯加大構(gòu)建時(shí)間,因?yàn)槊總€(gè)產(chǎn)品線是單獨(dú)做 資源依賴調(diào)整,資源依賴檢查,資源依賴合并,編譯,合包,簽名的
故多一條產(chǎn)品線,將多出20%到40%的額外出包時(shí)間
增加構(gòu)建內(nèi)存
- 內(nèi)存不夠報(bào)錯(cuò)
android studio java.lang.OutOfMemoryError: Java heap space
解決方法 工程根 gradle.properties
加入配置
# JNI編譯支持過時(shí)API
# android.useDeprecatedNdk=true
# 守護(hù)進(jìn)程
# org.gradle.daemon=true
# 按需編譯
# org.gradle.configureondemand=true
org.gradle.parallel=true
# 設(shè)置編譯jvm參數(shù)
org.gradle.jvmargs=-Xmx2048m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# org.gradle.jvmargs=-Xmx5120M -XX:+HeapDumpOnOutOfMemoryError -XX:MaxPermSize=512m -XX:ReservedCodeCacheSize=90m
舊方式其實(shí)是無效的,警告如下
Warning:The `android.dexOptions.incremental` property is deprecated and it has no effect on the build process.
原因是在build.gradle
加入
dexOptions {
incremental true
javaMaxHeapSize "4g"
}
這個(gè)配置其實(shí)可以刪除
按需禁用不必要的 task 加速
例如
android {
buildTypes {
debug {
project.gradle.startParameter.excludedTaskNames.addAll([
'lint',
'check',
])
}
}
意思是在 android 構(gòu)建的debug模式下,禁止 帶有 lint check 的任務(wù)
禁用 Lint 檢查加速構(gòu)建
Android Lint是在ADT16引入的一個(gè)新工具,它能夠掃描到安卓項(xiàng)目中的潛在bug,它既可以作為命令行使用,也可以在eclipse和as等集成環(huán)境中使用
http://tools.android.com/tips/lint
Lint 可以檢查的問題有
- Missing translations (and unused translations)
- Layout performance problems (all the issues the old layoutopt tool used to find, and more)
- Unused resources
- Inconsistent array sizes (when arrays are defined in multiple configurations)
- Accessibility and internationalization problems (hardcoded strings, missing contentDescription, etc)
- Icon problems (like missing densities, duplicate icons, wrong sizes, etc)
- Usability problems (like not specifying an input type on a text field)
- Manifest errors
Lint 工具是與集成開發(fā)環(huán)境無關(guān),本身檢查會(huì)比較耗時(shí),可以禁用掉
禁用Lint會(huì)導(dǎo)致一些副作用,比如開發(fā)者寫作垃圾代碼之類
Android 插件下禁用
在需要禁用的子模塊 build.gradle
中添加
android {
lintOptions {
abortonError false
}
}
或者
android {
lintOptions {
tasks.lint.enabled = false
}
}
gradle DSL 方式禁用
工程 根目錄 build.gradle
中添加
task lintCheck() {
getAllTasks(true).each {
def lintTasks = it.value.findAll { it.name.contains("lint") }
lintTasks.each {
it.enabled = false
}
}
}
或者 在需要禁用的子模塊 build.gradle
中apply plugin: 'com.android.application'
之前
beforeEvaluate {
if (task.name.contains("lint")) {
task.enabled = false
}
}
// 這段可能報(bào)錯(cuò),建議用上面的
tasks.whenTaskAdded { task ->
if (task.name.equals("lint")) {
task.enabled = false
}
}
gradke 編譯依賴優(yōu)化
管理依賴配置
在工程根目錄創(chuàng)建文件 package.gradle
,內(nèi)容為
subprojects {
apply plugin: 'maven'
apply plugin: 'idea'
ext {
test_depends = [
junit : 'junit:junit:4.6',
mockito_core : 'org.mockito:mockito-core:2.7.22',
robolectric : 'org.robolectric:robolectric:3.3.2',
robolectric_shadows_support_v4: 'org.robolectric:shadows-support-v4:3.3.2',
easymock : 'org.easymock:easymock:3.4',
powermock_core : 'org.powermock:powermock-core:1.6.5',
powermock_module_junit4 : 'org.powermock:powermock-module-junit4:1.6.5',
powermock_api_easymock : 'org.powermock:powermock-api-easymock:1.6.5',
]
android_test_depends = [
robotium_solo: 'com.jayway.android.robotium:robotium-solo:5.5.4'
]
apt_compiler = [
butterknife_compiler: 'com.jakewharton:butterknife-compiler:8.1.0',
]
provided_depends = [
]
depends = [
com_android_support_support_v4 : 'com.android.support:support-v4:25.0.1',
com_android_support_appcompat_7 : 'com.android.support:appcompat-v7:25.0.1',
com_android_support_support_annotations: 'com.android.support:support-annotations:25.0.1',
com_android_support_recyclerview_v7 : 'com.android.support:recyclerview-v7:25.0.1',
com_android_support_cardview_v7 : 'com.android.support:cardview-v7:25.0.1',
com_android_support_design : 'com.android.support:design:25.0.1',
com_android_constraint_layout : 'com.android.support.constraint:constraint-layout:1.0.2',
butterknife : 'com.jakewharton:butterknife:8.1.0',
]
component_depends = [
recyclerview_helper: 'com.define.android:recyclerview-helper:1.1.1',
define_dialog : 'com.define.android:define-dialog:1.1.0',
]
res_provided = [
]
res_depends = [
]
}
}
開發(fā)依賴庫被分為 三級(jí),分別是
- depends 三方依賴 provided_depends 三方非執(zhí)行依賴
- component_depends 組件依賴
- res_depends 資源模塊依賴 res_provided 資源模塊非執(zhí)行依賴
分類的依賴的目的是為了便于管理,
語義化依賴結(jié)構(gòu)
在工程根目錄的 build.gradle
第一行添加
apply from: rootProject.file("package.gradle")
所有模塊 build.gradle
中就可以使用package.gradle
配置的
dependencies {
// implementation fileTree(include: ['*.jar'], dir: 'libs')
// test start
testImplementation test_depends.junit,
test_depends.mockito_core,
test_depends.robolectric,
test_depends.robolectric_shadows_support_v4
androidTestImplementation android_test_depends.robotium_solo
// test end
apt apt_compiler.butterknife_compiler
implementation depends.com_android_support_support_v4,
depends.com_android_support_appcompat_7,
// implementation.com_android_support_recyclerview_v7,
// implementation.com_android_support_cardview_v7,
// implementation.com_android_support_design,
depends.butterknife,
project(':yourMoudle')
implementation component_depends.recyclerview_helper
}
查詢依賴配置
./gradlew -q :[module]:dependencies --refresh-dependencies
可以去掉 --refresh-dependencies 強(qiáng)制更新最新依賴
查詢某個(gè)生產(chǎn)線的編譯依賴
這個(gè)需求在 多生產(chǎn)線 productFlavors
構(gòu)建時(shí)特別重要
因?yàn)楫a(chǎn)品線的依賴,是在真實(shí)構(gòu)建合并依賴并輸出的,不是配置什么就依賴什么!
# 查詢輸出模塊 app 下所有的生產(chǎn)線的編譯依賴名稱
./gradlew app:dependencies | grep CompileClasspath
# 查詢輸出模塊 app 下所有的生產(chǎn)線的發(fā)布模式編譯依賴名稱
./gradlew app:dependencies | grep ReleaseCompileClasspath
# 輸出生產(chǎn)線 gray 發(fā)布模式編譯依賴詳情,configuration 后面跟的參數(shù)輸入必須在查詢中存在
./gradlew app:dependencies --configuration grayReleaseCompileClasspath
鎖定依賴提高編譯效率
不要在 gradle 中配置動(dòng)態(tài)版本的依賴,如下這幾種寫法
implementation group.id.1.+;
implementation group.id.latest.integration;
implementation group.id.latest.release;
因?yàn)檫@個(gè)會(huì)大大提高依賴查找的復(fù)雜度,導(dǎo)致gradle在編譯準(zhǔn)備起大量超時(shí),如果是做了生產(chǎn)線分離的項(xiàng)目,耗時(shí)尤其突出
一種解決方案是 去掉所有的動(dòng)態(tài)版本標(biāo)識(shí)
另一種,使用 gradle 在 2.0 以后提供的依賴鎖功能
configurations.all {
resolutionStrategy {
force 'group:id:x.x.x'
}
}
快照版本的依賴更新緩慢
在工程的根下配置,設(shè)置動(dòng)態(tài)版本只在 10min 內(nèi)有效
configurations.all {
resolutionStrategy {
// cache dynamic versions for 10 minutes
cacheDynamicVersionsFor 10*60, 'seconds'
// don't cache changing modules at all
cacheChangingModulesFor 10*60, 'seconds'
}
}
或者,每次包含編譯任務(wù)的task
執(zhí)行 --refresh-dependencies