android aar縮短構(gòu)建時間

前言

為啥要起這個名字呢,因為隨著項目越來越大,難免會遇到構(gòu)建速度越來越慢的問題,這個時候如何提高構(gòu)建速度就是我們需要考慮的問題了
這個適合于有一定android studio/gradle 構(gòu)建基礎(chǔ)的人觀看

其他解決方案

網(wǎng)上普遍有一些大家copy來copy去的答案,比如什么offline,也就是離線模式
開啟守護進程等方案
還有修改jvm的內(nèi)存大小

這些方案或多或少都看到過,但是修改這些對于我的項目沒有太多幫助

開發(fā)環(huán)境

android studio 2.3.3
mac
kotlin+java

這里就要說下我的項目研發(fā)過程

最初只有一個library,一個app,兩個module

mylibrary:
library是一個基礎(chǔ)項目,其中基本都是一些單類/utils的幫助工具,也是我多年開發(fā)的積累,或者是二次封裝的http請求庫

但是,因為業(yè)務(wù)發(fā)展,多了一個新的app,那我就將原來的app項目拆開
多了一個base的module,用于存放我的業(yè)務(wù)邏輯相關(guān)的基礎(chǔ)類庫

比如我封裝了自己的BaseApplication,這個Application中有我項目中需要初始化的數(shù)據(jù),比如數(shù)據(jù)數(shù)據(jù)統(tǒng)計SDK,crash上報SDK,初始化一些Service,比如更新應(yīng)用的Service,藍牙連接模塊的Service,都是所有項目都要用到的

另外還有BaseActivity,BaseFragment,BaseAdapter,網(wǎng)絡(luò)訪問的共有參數(shù)的封裝,數(shù)據(jù)傳輸加密方案的封裝

原app拆出來,稱為app1,新app也是一個module,稱為app2,一共是4個module了

后來我這里有業(yè)務(wù)需要,要接入二維碼掃碼,因為二維碼掃碼大家都是用的Zxing封裝庫,所以我也從網(wǎng)上找了一個,這個庫比較靠譜,有橫向/縱向/zxinglibrary的基礎(chǔ)庫,也就是3個庫,并且讓base依賴這個zxing項目,

在最初,我只有2個module,中期開始,也只有4個,勉強可以接受
現(xiàn)在:我有7個module了,而且后續(xù)又要開新的app開發(fā)項目,那么我就有8個module,并且項目間的依賴是

mylibrary-base-app1
zxinglibrary-pzxing-base-app1

也就是說我這里app項目的構(gòu)建有5個module參與,并且每次初次構(gòu)建時間超過3分鐘,這個時候我就有一個念頭,我要將不常用的模塊或者項目做成aar包,以縮減我的構(gòu)筑時間

制作aar包

這個我相信很多人都會,也很簡單,比如你運行了app1,然后library/base,中的build/output中都會生成結(jié)尾為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一下,發(fā)現(xiàn)base中沒有問題,但是app中會報找不到引用,這個是因為aar只會將本module的相關(guān)資源/classes放到里面來,而不會關(guān)聯(lián)引用

舉個栗子

比如你的base依賴了mylibrary工程,而mylibrary工程中引用了v7包的東西,而你在原來使用compile project應(yīng)用的時候,你的base不需要引用v7包,也可以直接調(diào)用到v7的資源,因為你的mylibrary會將引用傳遞過來,而你使用mylibrary的aar包作為依賴的時候就不會這樣了,你如果需要使用v7的資源,你需要自己依賴 compile "com.android.support:appcompat-v7:$androidSupportVersion";

同理,這里雖然base引用了aar,但是你的app是無法直接調(diào)用aar的

這樣我們就需要在app的build.gradle中同樣引用這幾個aar了

在project根目錄中創(chuàng)建一個allproject.gradle

這個gradle的目的是將一些共有的引用/配置放到這里來,后面只需要引用到這個gradle,就可以直接調(diào)用相關(guān)的配置,而不用

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 {
            //開發(fā)版
            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,就可以使用共有的構(gòu)建方案,引用同一個aar,根據(jù)不同的包名簽名輸出包的文件名不同

結(jié)果

原本的sync時間,3:00左右,現(xiàn)在gradle修改后的sync時間縮短到0:40~1:20,初次構(gòu)建時間由3分鐘縮短到1分20秒,instant run的時間由1分30秒縮短到40秒左右

后記

修改的過程趟了一些坑

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

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,168評論 25 708
  • 本文原作者為:kale2010 .blog地址:http://www.cnblogs.com/tianzhijie...
    NoValue閱讀 3,728評論 0 11
  • 一.榜單介紹 排行榜包括四大類: 單一框架:僅提供路由、網(wǎng)絡(luò)層、UI層、通信層或其他單一功能的框架 混合開發(fā)框架:...
    偉子男閱讀 5,369評論 0 161
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,635評論 19 139
  • 本想要一片凈土安放心靈,怎奈被凡塵亂世左右!空空蕩蕩無處安放。 曾幾何時我在這喧囂的城市失去自我,丟失了多少純真,...
    無我無我閱讀 281評論 0 0

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