前言
为啥要起这个名字呢,因为随着项目越来越大,难免会遇到构建速度越来越慢的问题,这个时候如何提高构建速度就是我们需要考虑的问题了
这个适合于有一定android studio/gradle 构建基础的人观看
其他解决方案
网上普遍有一些大家copy来copy去的答案,比如什么offline,也就是离线模式
开启守护进程等方案
还有修改jvm的内存大小
这些方案或多或少都看到过,但是修改这些对于我的项目没有太多帮助
开发环境
android studio 2.3.3
mac
kotlin+java
这里就要说下我的项目研发过程
最初只有一个library,一个app,两个module
mylibrary:
library是一个基础项目,其中基本都是一些单类/utils的帮助工具,也是我多年开发的积累,或者是二次封装的http请求库
但是,因为业务发展,多了一个新的app,那我就将原来的app项目拆开
多了一个base的module,用于存放我的业务逻辑相关的基础类库
比如我封装了自己的BaseApplication,这个Application中有我项目中需要初始化的数据,比如数据数据统计SDK,crash上报SDK,初始化一些Service,比如更新应用的Service,蓝牙连接模块的Service,都是所有项目都要用到的
另外还有BaseActivity,BaseFragment,BaseAdapter,网络访问的共有参数的封装,数据传输加密方案的封装
原app拆出来,称为app1,新app也是一个module,称为app2,一共是4个module了
后来我这里有业务需要,要接入二维码扫码,因为二维码扫码大家都是用的Zxing封装库,所以我也从网上找了一个,这个库比较靠谱,有横向/纵向/zxinglibrary的基础库,也就是3个库,并且让base依赖这个zxing项目,
在最初,我只有2个module,中期开始,也只有4个,勉强可以接受
现在:我有7个module了,而且后续又要开新的app开发项目,那么我就有8个module,并且项目间的依赖是
mylibrary-base-app1
zxinglibrary-pzxing-base-app1
也就是说我这里app项目的构建有5个module参与,并且每次初次构建时间超过3分钟,这个时候我就有一个念头,我要将不常用的模块或者项目做成aar包,以缩减我的构筑时间
制作aar包
这个我相信很多人都会,也很简单,比如你运行了app1,然后library/base,中的build/output中都会生成结尾为aar的包,一个是debug的一个是release的,这样的情况下,我们就可以引用这个aar包作为依赖
我这里因为base有可能今后还会频繁修改,所以暂时将zxinglibrary,pzxing,mylibrary
引用过程
repositories {
mavenCentral()
flatDir {
dirs '../base/libs'
}
}
dependencies{
...
compile(name:'mylibrary-release',ext:'aar')
compile(name: 'portraitzxing-release', ext: 'aar')
compile(name: 'zxinglibrary-release', ext: 'aar')
}
报错
这个是在base中的引用,sync一下,发现base中没有问题,但是app中会报找不到引用,这个是因为aar只会将本module的相关资源/classes放到里面来,而不会关联引用
举个栗子
比如你的base依赖了mylibrary工程,而mylibrary工程中引用了v7包的东西,而你在原来使用compile project应用的时候,你的base不需要引用v7包,也可以直接调用到v7的资源,因为你的mylibrary会将引用传递过来,而你使用mylibrary的aar包作为依赖的时候就不会这样了,你如果需要使用v7的资源,你需要自己依赖 compile "com.android.support:appcompat-v7:$androidSupportVersion";
同理,这里虽然base引用了aar,但是你的app是无法直接调用aar的
这样我们就需要在app的build.gradle中同样引用这几个aar了
在project根目录中创建一个allproject.gradle
这个gradle的目的是将一些共有的引用/配置放到这里来,后面只需要引用到这个gradle,就可以直接调用相关的配置,而不用
allproject.gradle
import java.text.SimpleDateFormat
apply plugin: 'com.android.application'
repositories {
mavenCentral()
flatDir {
dirs '../base/libs'
}
}
dependencies {
compile(name: 'mylibrary-release', ext: 'aar')
compile(name: 'portraitzxing-release', ext: 'aar')
compile(name: 'zxinglibrary-release', ext: 'aar')
}
android {
signingConfigs {
config {
def dir = rootDir
storeFile file("${dir}/abc.jks")
storePassword "123341"
keyAlias "abc"
keyPassword "123341"
v2SigningEnabled false
}
}
compileSdkVersion compile_version
buildToolsVersion build_tools_version
//日期
SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd")
def dString = df.format(System.currentTimeMillis())
def service = "B"
def device = "M"
def os = "A"
def date = dString //第四至十一位:日期;
def index = "01" //第12到13位:流水号
def cate = "B" //14位:类型 B代表beta版,V代表正式版;
def ver
def betaVer;
def releaseVer;
buildTypes {
dev {
//开发版
minifyEnabled false
cate = "D"
ver = service + device + os + date + index
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'app/proguard-rules.pro'
buildConfigField("String", "VER", '"' + ver + cate + '"')
def type = getHttpType()
buildConfigField("String", "type", '"' + type + '"')
buildConfigField("String", "type", '"test"')
buildConfigField("int", "cate", '1')
buildConfigField("boolean", "Dev", "true")
betaVer = ver;
signingConfig signingConfigs.config
debuggable true
}
debug {
//debug版本
minifyEnabled false
debuggable true
cate = "B"
ver = service + device + os + date + index
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'app/proguard-rules.pro'
buildConfigField("String", "VER", '"' + ver + cate + '"')
buildConfigField("boolean", "Dev", "false")
buildConfigField("String", "type", '"test"')
// buildConfigField("String", "type", '"www"')
buildConfigField("int", "cate", '2')
buildConfigField("boolean", "Dev", "false")
betaVer = ver;
signingConfig signingConfigs.config
}
release {
//正式版
// minifyEnabled false
// debuggable true
minifyEnabled true
debuggable false
cate = "V"
ver = service + device + os + date + index
proguardFiles 'proguard-rules.pro'
buildConfigField("String", "VER", '"' + ver + cate + '"')
buildConfigField("boolean", "Dev", "false")
buildConfigField("String", "type", '"www"')
buildConfigField("int", "cate", '0')
buildConfigField("boolean", "Dev", "false")
releaseVer = ver;
signingConfig signingConfigs.config
}
}
productFlavors {
mysite {
manifestPlaceholders = [CHANNEL_VALUE: "mysite"]
}
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
def buildType = variant.buildType
def type;
switch (buildType.name) {
case "release":
type = "V"
break
case "debug":
type = "B"
break
default:
type = "D"
}
println("buildType:" + buildType.name)
def fileName = "app${lastName(applicationId)}_${variant.productFlavors[0].name}_${ver}${type}.apk"
println("fileName = $fileName")
output.outputFile = new File(
output.outputFile.parent,
output.outputFile.name.replace(output.outputFile.name, fileName))
}
}
}
static String lastName(String applicationId) {
def split = applicationId.split("\\.")
return split[split.size() - 1]
}
app的build.gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply from: '../allproject.gradle'
android {
defaultConfig {
defaultConfig {
applicationId "com.kikt.application"
minSdkVersion min_version
targetSdkVersion target_version
versionCode 19
versionName "1.1.9"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
}
}
...
这样,每个项目中只需要apply from: '../allproject.gradle'
引用到这个gradle,就可以使用共有的构建方案,引用同一个aar,根据不同的包名签名输出包的文件名不同
结果
原本的sync时间,3:00左右,现在gradle修改后的sync时间缩短到0:40~1:20,初次构建时间由3分钟缩短到1分20秒,instant run的时间由1分30秒缩短到40秒左右
后记
修改的过程趟了一些坑