Gradle是Android项目新的编译系统,是基于JVM的进化版的编译工具;它从构建工具(如Ant 和Maven)汲取了经验教训。随着Android项目变得越来越复杂,模块化的开发实践变得越来越流行,编译性能至关重要。在每次编译时节省几秒能大大提高效率。
gradle assemble 生成所有渠道的Debug和Release包
gradle assembleDebug 生成所有渠道的Debug包
gradle assembleRelease 生成所有渠道的Release包
gradle assemblexxx 生成某个渠道的Debug和Release包
你可能已经意识到,即使最简单的Gradle 可以说相当慢,这里有一些提示,以提高gradle 任务的执行性能:
- Gradle守护进程
你可以减少Gradle的启动时间,如果你告诉Gradle使用守护进程来编译:
org.gradle.daemon=true
- 并行执行工程
如果你正在建立一个非常复杂的项目,并且有很多依赖的子模块,这会带来很大的不同:
多module依赖复杂慎用
org.gradle.parallel=true
-
按需配置项目
执行任务之前Gradle会配置每个项目,不管实际上该项目是否需要特定的编译。“按需配置”模式更改此行为,只配置所需的项目。像并行模式,按需配置会有很大影响对于多模块依赖的构建。 -
全局的gradle.properties
在我们的主目录中的属性文件中定义的属性优先于项目目录,因为你想在构建服务器上避免使用守护,在内存耗用比启动时间更重要的地方。
/Users/用户/.gradle/gradle.properties
# The Gradle daemon aims to improve the startup and execution time of Gradle.
# When set to true the Gradle daemon is to run the build.
org.gradle.daemon=true
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
org.gradle.parallel=true
# Enables new incubating mode that makes Gradle selective when configuring projects.
# Only relevant projects are configured which results in faster builds for large multi-projects.
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:configuration_on_demand
org.gradle.configureondemand=true
- Modules 消耗很高
如果该模块不经常修改,重要的是要考虑到这一点:从头开始编译需要时间,甚至检查以前的单个模块构建是否是最新的。依赖.jar/.aar效率更高。
优化 lint 任务执行时间
gradle build -x lint
更进一步
gradle build -x lint -x lintVitalRelease
屏蔽不需要的Task
提示 :如果你想从增量构建永久地跳过lint检查,在build.gradle添加:
//屏蔽系统Task
tasks.whenTaskAdded { task ->
if (task.name.equals("lint") //跳过lint检查
|| task.name.equals("clean") //如果instant run不生效,把clean这行去掉
|| task.name.equals("Aidl") //如果项目中有用到aidl,不可以舍弃这个任务
|| task.name.equals("mockableAndroidJar") //用不到测试的时候,可以先关闭
|| task.name.equals("UnitTest")
|| task.name.equals("AndroidTest")
|| task.name.equals("Ndk") //用不到NDK和JNI时候,可以先关闭
|| task.name.equals("Jni")
) {
task.enabled = false
}
}
//屏蔽指定Task
gradle.taskGraph.whenReady {
tasks.each { task ->
if(task.name.contains("XXX") {
task.enabled = false
}
}
}
原文:
https://android.jlelse.eu/speeding-up-gradle-builds-619c442113cb#.fwotrutph
官方关于Gradle的实用建议:
- 通过productFlavors设置build variant,针对不同的product保留对应的配置信息,加速构建,类似多渠道打包。
- 避免编译不必要的资源,如只使用英文string资源和xxhdpi的屏幕密度资源。
- 多渠道打包,本质是使用productFlavors ,结合占位符与AndroidManifest.xml的使用,可以为不同渠道设置不同包名。
productFlavors {
dev {
applicationIdSuffix ".debug" //不同包名设置,便于线上和开发包安装在同一手机
resConfigs "en", "xxhdpi"
}
googlepay {}
xiaomi {}
tencent {
manifestPlaceholders = [UMENG_CHANNEL: "Tencent"] //结合占位符
}
}
- 用静态的版本依赖,避免使用+号。
- 建议使用library模块,模块化代码抽离。
Gradle通用技巧
- Log开关控制。定义动态编译生成对象,通过buildConfigField控制,然后在代码中通过BuildConfig.enableLog来获取。
buildTypes {
debug {
buildConfigField("boolean", "enableLog", "true")
}
release{
buildConfigField("boolean", "enableLog", "false")
}
}
- 版本号、依赖统一管理。新建独立的gradle(config.gradle),然后apply from进当前的gradle,通过设置projext.ext,再通过rootProject.ext进行引用。
ext {
abortOnLintError = false
checkLintRelease = false
android = [compileSdkVersion : 24,
buildToolsVersion : "25.0.2",
applicationId : "com.skyseraph.xknife",
applicationIdUserLogin : "com.skyseraph.xknife.mod.userlogin",
applicationIdLaunch : "com.skyseraph.xknife.mod.launch",
applicationIdUpgrade : "com.skyseraph.xknife.mod.upgrade",
minSdkVersion : 15,
targetSdkVersion : 24,
versionCode : 1,
versionName : "0.0.1",
testInstrumentationRunner: "android.support.test.runner.AndroidJUnitRunner"
]
def supportVersion = "24.2.1"
def daggerVersion = "2.5"
def retrofitVersion = "2.1.0"
def okhttpVersion = "3.5.0"
def rxandroidVersion = "1.2.1"
def okioVersion = "1.9.0"
def gsonVersion = "2.8.0"
def glideVersion = "3.6.1"
def butterKnifeVersion = "8.1.0"
def leakcanary = "1.5.1"
def aspectVersion = "1.8.9"
dependencies = ["appcompat-v7" : "com.android.support:appcompat-v7:${supportVersion}",
"design" : "com.android.support:design:${supportVersion}",
"appcompat-v4" : "com.android.support:support-v4:${supportVersion}",
"recyclerview-v7" : "com.android.support:recyclerview-v7:${supportVersion}",
"cardview-v7" : "com.android.support:cardview-v7:${supportVersion}",
"junit" : "junit:junit:4.12",
// inject library
"butterknife" : "com.jakewharton:butterknife:${butterKnifeVersion}",
// graphics library
"glide" : "com.github.bumptech.glide:glide:${glideVersion}",
"gson" : "com.google.code.gson:gson:${gsonVersion}",
// retrofit + okhttp
"retrofit:retrofit" : "com.squareup.retrofit2:retrofit:${retrofitVersion}",
"retrofit:adapter-rxjava" : "com.squareup.retrofit2:adapter-rxjava:${retrofitVersion}",
"retrofit:converter-gson" : "com.squareup.retrofit2:converter-gson:${retrofitVersion}",
"retrofit;converter-scalars" : "com.squareup.retrofit2:converter-scalars:${retrofitVersion}",
"okhttp3:okhttp" : "com.squareup.okhttp3:okhttp:${okhttpVersion}",
"okhttp3:logging-interceptor": "com.squareup.okhttp3:logging-interceptor:${okhttpVersion}",
"okio" : "com.squareup.okio:okio:${okioVersion}",
"rxandroid" : "io.reactivex:rxandroid:${rxandroidVersion}",
// aspectjrt
"aspectjrt" : "org.aspectj:aspectjrt:${aspectVersion}",
// leakcanary
"leakcanary_debug" : "com.squareup.leakcanary:leakcanary-android:${leakcanary}",
"leakcanary_release" : "com.squareup.leakcanary:leakcanary-android-no-op:${leakcanary}",
"leakcanary_test" : "com.squareup.leakcanary:leakcanary-android-no-op:${leakcanary}",
]
}
//使用
applicationId rootProject.ext.android["applicationId"]
- apk输出名字定制化
applicationVariants.all { variant ->
variant.outputs.all { output ->
def fileName = "XKnife-${variant.buildType.name}-${variant.versionName}-${variant.productFlavors[0].name}.apk".toLowerCase()
def outFile = output.outputFile
if (outFile != null && outFile.name.endsWith('.apk')) {
outputFileName = fileName // output.outputFile 改为 outputFileName
}
}
}
- 构建不同的名称,版本号和AppID。
buildTypes {
// minifyEnabled 混淆处理
// shrinkResources 去除无用资源
// signingConfig 签名
// proguardFiles 混淆配置
// applicationIdSuffix 增加APP ID的后缀
// debuggable 是否保留调试信息
debug {
minifyEnabled false
debuggable true
applicationIdSuffix ".debug" //构建不同AppId
versionNameSuffix "-debug"
resValue "string", "app_name", " XXX(debug)"
signingConfig signingConfigs.debug
manifestPlaceholders = [UMENG_APPKEY_VALUE: "xxxxxxxx"] // 替换AndroidManifest中的占位符
buildConfigField "String", "UMENG_APPKEY", "\"xxxxxxx\""
buildConfigField "String", "HOST", "\"http://100.100.100.100:8888\""
buildConfigField "String", "API_URL", '"http://api.douban.com/v2/"'
}
release {
resValue "string", "app_name", " XXX"
manifestPlaceholders = [app_label: "@string/app_name"]
debuggable false
minifyEnabled true
shrinkResources true
signingConfig signingConfigs.release
// proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro',
project(":module:xkm_launch").file("proguard-rules.pro")
manifestPlaceholders = [UMENG_APPKEY_VALUE: "xxxxxx"]
buildConfigField "String", "UMENG_APPKEY", "\"xxxxxx\""
buildConfigField "String", "HOST", "\"http://xxx.xxx.com\""
buildConfigField "String", "API_URL", '"http://api.douban.com/v2/"'
}
preview {
applicationIdSuffix ".preview"
debuggable true
minifyEnabled true
shrinkResources true
signingConfig signingConfigs.preview
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
- 修改默认的Build配置文件名
rootProject.buildFileName = xx.gradle
- Java版本设置
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}