Android Gradle入門

對(duì)Gradle的疑問(wèn)

從剛學(xué)習(xí)Android開始,就對(duì)gradle有著好多疑問(wèn),隨著了解的越來(lái)越多,疑問(wèn)也越來(lái)越多。疑問(wèn)基本包括:gradle的作用是什么?gradle是怎么構(gòu)建Android項(xiàng)目的?gradle每個(gè)文件的作用?gradle文件中配置具體是配置啥,都是什么含義?怎么使用gradle?多模塊項(xiàng)目是怎么構(gòu)建的?怎么在多模塊中找到初始Activity?多模塊之間怎么通信?多模塊中每個(gè)模塊要怎么單獨(dú)運(yùn)行?
抱著上面的疑問(wèn),開啟對(duì)Gradle的研究。。。

Gradle在Android中的作用

  1. 作用:Gradle是一種構(gòu)建工具,它可以幫你管理項(xiàng)目中的差異,依賴,編譯,打包,部署......,你可以定義滿足自己需要的構(gòu)建邏輯,寫入到build.gradle中供日后復(fù)用.
  2. Gradle腳本是基于Groovy語(yǔ)言來(lái)編譯執(zhí)行的(Groovy 是一種 JVM 上的腳本語(yǔ)言,基于 java 擴(kuò)展的動(dòng)態(tài)語(yǔ)言)
  3. 總結(jié):一個(gè)可編程的工具,用來(lái)執(zhí)行一系列有序的任務(wù)來(lái)表達(dá)自動(dòng)化需求(編譯源代碼 -> 拷貝文件 -> 組裝構(gòu)建,當(dāng)然這些任務(wù)不是固定的,可能還有其他任務(wù))
  4. 再簡(jiǎn)單一點(diǎn):Gradle就是自動(dòng)化的編譯、打包程序
  5. Gradle官網(wǎng)文檔
  6. gradle學(xué)習(xí)系列文章
  7. Android Gradle 完整指南

Groovy的簡(jiǎn)單介紹:

本地只簡(jiǎn)單介紹一下 Groovy 在 Android 中的使用,要想深入了解需看gradle學(xué)習(xí)系列文章

  1. Task:在Gradle中一個(gè)原子性的操作叫做 task,簡(jiǎn)單理解為task是Gradle腳本中的最小可執(zhí)行單元。但是要是執(zhí)行g(shù)radle文件中某個(gè)task,會(huì)發(fā)現(xiàn)所有task都被執(zhí)行

  2. Task Actions:一個(gè) Task 是由一序列 Action (動(dòng)作)組成的,當(dāng)運(yùn)行一個(gè) Task 的時(shí)候,這個(gè) Task 里的 Action 序列會(huì)按順序依次執(zhí)行。Gralde 里通過(guò) doFirst、doLast 來(lái)為 Task 增加 Action 。doFirst:task執(zhí)行時(shí)最先執(zhí)行的操作doLast:task執(zhí)行時(shí)最后執(zhí)行的操作

  3. Project:每一個(gè) build.gradle 腳本文件被 Gradle 加載解析后,都會(huì)對(duì)應(yīng)生成一個(gè) Project 對(duì)象,在腳本中的配置方法其實(shí)都對(duì)應(yīng)著 Project 中的API

  4. Extension:Android中 gradle腳本中添加的類似android這種命名空間的配置就是extension,翻譯成中文意思就叫擴(kuò)展。它的作用就是通過(guò)實(shí)現(xiàn)自定義的 Extension,可以在 Gradle 腳本中增加類似 android 這樣命名空間的配置,Gradle 可以識(shí)別這種配置,并讀取里面的配置內(nèi)容

    • 嵌套Extension:Extension可以嵌套,類似于內(nèi)部類的寫法,在Android項(xiàng)目的gradle中隨處可見
    • Android中的Extension:


      Android中的Extension.png
  5. NamedDomainObjectContainer:顧名思義就是命名領(lǐng)域?qū)ο笕萜?,它的主要功能有?/p>

    • 它能夠通過(guò)DSL(在Gradle腳本中)創(chuàng)建指定 type 的對(duì)象實(shí)例;
    • 指定的 type 必須有一個(gè) public 構(gòu)造函數(shù),且必須帶有一個(gè) String name 的參數(shù),type 類型的領(lǐng)域?qū)ο蟊仨氂忻麨椤皀ame”的屬性;
    • 它是一個(gè)實(shí)現(xiàn)了 SortedSet 接口的容器,所以所有領(lǐng)域?qū)ο蟮?name 屬性值都必須是唯一的,在容器內(nèi)部會(huì)用 name 屬性來(lái)排序;

Gradle在Android中的運(yùn)用

Gradle的幾個(gè)核心類型(主要從Android項(xiàng)目的角度)

Project:表示需要構(gòu)建的一個(gè)項(xiàng)目,類似Android項(xiàng)目的一個(gè)module,Project和build.gradle是一一對(duì)應(yīng)的。Project提供了一套api用來(lái)查看工程信息。
Task:對(duì)一個(gè)項(xiàng)目的構(gòu)建,就是對(duì)該項(xiàng)目中Task集合的運(yùn)行,每個(gè)Task執(zhí)行一些基本的工作,比如:編譯、運(yùn)行單元測(cè)試、壓縮成apk等
build.gradle:構(gòu)建腳本(相當(dāng)于maven的pom.xml)
gradle.properties:屬性文件,每個(gè)項(xiàng)目可以創(chuàng)建屬性文件也可以不創(chuàng)建。
setting.gradle:聲明所需的配置來(lái)實(shí)例化項(xiàng)目的層次結(jié)構(gòu)(意思就類似編譯整個(gè)大工程,需要包含哪些模塊一起編譯)

Android Studio通過(guò)Gradle構(gòu)建項(xiàng)目的文件介紹

gradle文件目錄.png

項(xiàng)目結(jié)構(gòu).png

以上文件結(jié)構(gòu)表明:Android項(xiàng)目是Gradle通過(guò)多模塊構(gòu)建的

各文件作用介紹:

  1. settings.gradleGradle:使用該文件來(lái)配置多項(xiàng)目構(gòu)建。它應(yīng)該由一行代碼組成:include ':app'
    這告訴Gradle app子目錄也是一個(gè)Gradle項(xiàng)目。如果在稍后的時(shí)間,您要通過(guò)可用的向?qū)ndroid庫(kù)添加到此項(xiàng)目中,則會(huì)創(chuàng)建另一個(gè)項(xiàng)目子目錄并將其添加到此文件中。

    1. 我們?cè)?Android 應(yīng)用開發(fā)中,一個(gè) Project 可以包含若干個(gè) module ,這種就叫做多項(xiàng)目構(gòu)建。在 Android Studio 項(xiàng)目中,根目錄都有一個(gè)名叫 settings.gradle 的文件,然后每個(gè) module 的根目錄中又有一個(gè) build.gradle 文件,Gradle 就是通過(guò) settings.gradle 來(lái)進(jìn)行多項(xiàng)目構(gòu)建的。
    2. Gradle 在運(yùn)行時(shí)會(huì)讀取并解析 settings.gradle 文件,生成一個(gè) Settings對(duì)象,然后從中讀取并解析子項(xiàng)目的 build.gradle 文件,然后為每個(gè) build.gradle 文件生成一個(gè) Project 對(duì)象,進(jìn)而組裝一個(gè)多項(xiàng)目構(gòu)建出來(lái)。
    3. Settings 里最核心的API就是 include 方法,通過(guò)該方法引入需要構(gòu)建的子項(xiàng)目。
  2. gradle-wrapper.properties:它配置了所謂的Gradle Wrapper。這使您可以構(gòu)建Android項(xiàng)目,而無(wú)需首先安裝Gradle,其一般結(jié)構(gòu)如下:

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip

前四行表示當(dāng)包裝首次運(yùn)行時(shí),它將下載Gradle發(fā)行版并將其存儲(chǔ)在主目錄.gradle/wrapper/dists中的目錄中。最后一行distributionUrl是Gradle的下載地址

  1. gradle.propertie 文件:
    1. 在與 build.gradle 文件同級(jí)目錄下,定義一個(gè)名為 gradle.properties 文件,里面定義的鍵值對(duì),可以在 Project 中直接訪問(wèn):
      gradle.properties里定義屬性值:company="hangzhouheima"
      在 build.gradle 文件里可以這樣直接訪問(wèn):println company = ${company}
    2. 擴(kuò)展屬性:可以通過(guò) ext 命名空間來(lái)定義屬性,我們稱之為擴(kuò)展屬性:
      定義屬性:ext {username = "hjy" age = 30}
      使用屬性:println username
  1. build.gradle:史上最全Android build.gradle配置詳解

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript { //這里是gradle腳本執(zhí)行所需依賴,分別是對(duì)應(yīng)的maven庫(kù)和插件
    
    repositories {
        google() //從Android Studio3.0后新增了google()配置,可以引用google上的開源項(xiàng)目
        jcenter() //是一個(gè)類似于github的代碼托管倉(cāng)庫(kù),聲明了jcenter()配置,可以輕松引用 jcenter上的開源項(xiàng)目
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0' //此處是android的插件gradle,gradle是一個(gè)強(qiáng)大的項(xiàng)目構(gòu)建工具

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }}

allprojects { //這里是項(xiàng)目本身需要的依賴,比如項(xiàng)目所需的maven庫(kù)
    repositories {
        google()
        jcenter()
    }}

// 運(yùn)行g(shù)radle clean時(shí),執(zhí)行此處定義的task任務(wù)。
// 該任務(wù)繼承自Delete,刪除根目錄中的build目錄。
// 相當(dāng)于執(zhí)行Delete.delete(rootProject.buildDir)。
// gradle使用groovy語(yǔ)言,調(diào)用method時(shí)可以不用加()。
task clean(type: Delete) {
    delete rootProject.buildDir
}

方法解析:
1. apply:apply(options: Map<String, ?>):

我們通過(guò)該方法使用插件或者是其他腳本,options里主要選項(xiàng)有:

  • from: 使用其他腳本,值可以為 Project.uri(Object) 支持的路徑
  • plugin:使用其他插件,值可以為插件id或者是插件的具體實(shí)現(xiàn)類例如:

//使用插件,com.android.application 就是插件id
apply plugin: 'com.android.application'
//使用插件,MyPluginImpl 就是一個(gè)Plugin接口的實(shí)現(xiàn)類
apply plugin: MyPluginImpl
//引用其他gradle腳本,push.gradle就是另外一個(gè)gradle腳本文件
apply from: './push.gradle'

文件中第一行使用apply plugin表示應(yīng)用了一個(gè)插件,其中提供了Android 編譯、測(cè)試、打包等等的所有task,該插件一般有兩種值可選:

  • com.android.application:表示該模塊為應(yīng)用程序模塊,可以直接運(yùn)行,打包得到的是.apk文件
  • com.android.library:表示該模塊為庫(kù)模塊,只能作為代碼庫(kù)依附于別的應(yīng)用程序模塊來(lái)運(yùn)行,打包得到的是.aar文件

2. 對(duì)Project進(jìn)行配置:

//通過(guò)path定位并獲取該 Project 對(duì)象
project(path: String): Project
//通過(guò)path定位一個(gè)Project,并進(jìn)行配置
project(path: String, config: Closure): Project
//針對(duì)所有項(xiàng)目進(jìn)行配置,但是為了保證每個(gè)項(xiàng)目的獨(dú)立性,我們一般不會(huì)在這里面操作太多共有的東西。
allprojects(config: Closure)
//針對(duì)所有子項(xiàng)目進(jìn)行配置
subprojects(config: Closure)

3. 其中幾個(gè) {...} 閉包 解釋下:

buildscript {...} --> 定義了 Android 編譯工具(gradle)的類路徑。聲明倉(cāng)庫(kù)、添加插件專用閉包。就是對(duì)gradle的配置
repositories {...} --> 就是代碼倉(cāng)庫(kù),我們平時(shí)的添加的一些 dependency 就是從這里下載的。 jCenter是一個(gè)著名的 Maven 倉(cāng)庫(kù)。
dependencies {...} --> 添加插件、遠(yuǎn)程依賴
apply --> 使用插件,插件雖然導(dǎo)入進(jìn)來(lái)了,但是子項(xiàng)目用不用就是個(gè)事了,要是不用的話,是不需要打包進(jìn)來(lái)的,所以要主動(dòng)聲明下
每個(gè)項(xiàng)目單獨(dú)的 build.gradle --> 針對(duì)每個(gè)moudle 的配置,如果這里的定義的選項(xiàng)和頂層build.gradle定義的相同,頂層build.gradle會(huì)被覆蓋

4. 依賴的添加格式: group:name:version(組名:庫(kù)名稱:版本號(hào))

舉例:implementation 'androidx.appcompat:appcompat:1.2.0'
本地依賴:通過(guò)files()方法可以添加文件依賴,如果有很多jar文件,我們也可以通過(guò)fileTree()方法添加一個(gè)文件夾,除此之外,我們還可以通過(guò)通配符的方式添加:implementation fileTree(dir: 'libs', include: ['*.jar'])

每個(gè)項(xiàng)目單獨(dú)的 build.gradle

apply plugin: 'com.android.application'

android {    
    compileSdkVersion 29 
    buildToolsVersion "30.0.2"
    
    defaultConfig {
        applicationId "com.wang.text"
        minSdkVersion 23
        targetSdkVersion 29
        versionCode 1
        versionName "1.0" 
        
        testInstrumentationRunner  "androidx.test.runner.AndroidJUnitRunner"
    }
    
    buildTypes {
        release { 
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation project(path: ':module_two'
}
  • apply plugin:第一行代碼應(yīng)用了Android 程序的gradle插件,作為Android 的應(yīng)用程序,這一步是必須的,因?yàn)閜lugin中提供了Android 編譯、測(cè)試、打包等等的所有task。
  • android:這是編譯文件中最大的代碼塊,關(guān)于android 的所有特殊配置都在這里,這就是又我們前面的聲明的 plugin 提供的。
  1. defaultConfig就是程序的默認(rèn)配置,注意,如果在AndroidMainfest.xml里面定義了與這里相同的屬性,會(huì)以這里的為主。
  2. 這里最有必要要說(shuō)明的是applicationId的選項(xiàng):在我們?cè)?jīng)定義的AndroidManifest.xml中,那里定義的包名有兩個(gè)用途:一個(gè)是作為程序的唯一識(shí)別ID,防止在同一手機(jī)裝兩個(gè)一樣的程序;另一個(gè)就是作為我們R資源類的包名。在以前我們修改這個(gè)ID會(huì)導(dǎo)致所有用引用R資源類的地方都要修改。但是現(xiàn)在我們?nèi)绻薷腶pplicationId只會(huì)修改當(dāng)前程序的ID,而不會(huì)去修改源碼中資源文件的引用。
  • buildTypes:定義了編譯類型,針對(duì)每個(gè)類型我們可以有不同的編譯配置,不同的編譯配置對(duì)應(yīng)的有不同的編譯命令。默認(rèn)的有debug、release 的類型。
  • dependencies:是屬于gradle 的依賴配置。它定義了當(dāng)前項(xiàng)目需要依賴的其他庫(kù)。
Module完整的build.gradle配置如下
// 聲明是Android程序,//com.android.application 表示這是一個(gè)應(yīng)用程序模塊//com.android.library 標(biāo)識(shí)這是一個(gè)庫(kù)模塊//而這區(qū)別:前者可以直接運(yùn)行,后著是依附別的應(yīng)用程序運(yùn)行
apply plugin: 'com.android.application'

android {
    signingConfigs {// 自動(dòng)化打包配置,簽名
        release {// 線上環(huán)境
            keyAlias 'test'
            keyPassword '123456'
            storeFile file('test.jks')
            storePassword '123456'
        }
        debug {// 開發(fā)環(huán)境
            keyAlias 'test'
            keyPassword '123456'
            storeFile file('test.jks')
            storePassword '123456'
        }
    }
    compileSdkVersion 27//設(shè)置編譯時(shí)用的Android版本
    defaultConfig {
        applicationId "com.billy.myapplication"http://項(xiàng)目的包名
        minSdkVersion 16//項(xiàng)目最低兼容的版本
        targetSdkVersion 27//項(xiàng)目的目標(biāo)版本
        versionCode 1//版本號(hào)
        versionName "1.0"http://版本名稱
        flavorDimensions "versionCode"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"http://表明要使用AndroidJUnitRunner進(jìn)行單元測(cè)試
    }
    buildTypes {// 生產(chǎn)/測(cè)試環(huán)境配置
        release {// 生產(chǎn)環(huán)境
            buildConfigField("boolean", "LOG_DEBUG", "false")//配置Log日志
            buildConfigField("String", "URL_PERFIX", "\"https://release.cn/\"")// 配置URL前綴
            minifyEnabled false//是否對(duì)代碼進(jìn)行混淆
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//指定混淆的規(guī)則文件
            signingConfig signingConfigs.release//設(shè)置簽名信息
            pseudoLocalesEnabled false//是否在APK中生成偽語(yǔ)言環(huán)境,幫助國(guó)際化的東西,一般使用的不多
            zipAlignEnabled true//是否對(duì)APK包執(zhí)行ZIP對(duì)齊優(yōu)化,減小zip體積,增加運(yùn)行效率
            applicationIdSuffix 'test'//在applicationId 中添加了一個(gè)后綴,一般使用的不多
            versionNameSuffix 'test'//在applicationId 中添加了一個(gè)后綴,一般使用的不多
        }
        debug {// 測(cè)試環(huán)境
            buildConfigField("boolean", "LOG_DEBUG", "true")//配置Log日志
            buildConfigField("String", "URL_PERFIX", "\"https://test.com/\"")// 配置URL前綴
            minifyEnabled false//是否對(duì)代碼進(jìn)行混淆
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//指定混淆的規(guī)則文件
            signingConfig signingConfigs.debug//設(shè)置簽名信息
            debuggable false//是否支持?jǐn)帱c(diǎn)調(diào)試
            jniDebuggable false//是否可以調(diào)試NDK代碼
            renderscriptDebuggable false//是否開啟渲染腳本就是一些c寫的渲染方法
            zipAlignEnabled true//是否對(duì)APK包執(zhí)行ZIP對(duì)齊優(yōu)化,減小zip體積,增加運(yùn)行效率
            pseudoLocalesEnabled false//是否在APK中生成偽語(yǔ)言環(huán)境,幫助國(guó)際化的東西,一般使用的不多
            applicationIdSuffix 'test'//在applicationId 中添加了一個(gè)后綴,一般使用的不多
            versionNameSuffix 'test'//在applicationId 中添加了一個(gè)后綴,一般使用的不多
        }
    }

    sourceSets {//目錄指向配置
        main {
            jniLibs.srcDirs = ['libs']//指定lib庫(kù)目錄
        }
    }

    packagingOptions{//打包時(shí)的相關(guān)配置
        //pickFirsts做用是 當(dāng)有重復(fù)文件時(shí) 打包會(huì)報(bào)錯(cuò) 這樣配置會(huì)使用第一個(gè)匹配的文件打包進(jìn)入apk
        // 表示當(dāng)apk中有重復(fù)的META-INF目錄下有重復(fù)的LICENSE文件時(shí)  只用第一個(gè) 這樣打包就不會(huì)報(bào)錯(cuò)
        pickFirsts = ['META-INF/LICENSE']

        //merges何必 當(dāng)出現(xiàn)重復(fù)文件時(shí) 合并重復(fù)的文件 然后打包入apk
        //這個(gè)是有默認(rèn)值得 merges = [] 這樣會(huì)把默默認(rèn)值去掉  所以我們用下面這種方式 在默認(rèn)值后添加
        merge 'META-INF/LICENSE'

        //這個(gè)是在同時(shí)使用butterknife、dagger2做的一個(gè)處理。同理,遇到類似的問(wèn)題,只要根據(jù)gradle的提示,做類似處理即可。
        exclude 'META-INF/services/javax.annotation.processing.Processor'
    }

    productFlavors {  
        wandoujia {}
        xiaomi {}
        _360 {}
    }

    productFlavors.all {
            //批量修改,類似一個(gè)循序遍歷
        flavor -> flavor.manifestPlaceholders = [IFLYTEK_CHANNEL: name]
    }

    //程序在編譯的時(shí)候會(huì)檢查lint,有任何錯(cuò)誤提示會(huì)停止build,我們可以關(guān)閉這個(gè)開關(guān)
    lintOptions {
        abortOnError false
        //即使報(bào)錯(cuò)也不會(huì)停止打包
        checkReleaseBuilds false
        //打包release版本的時(shí)候進(jìn)行檢測(cè)
    }

}

dependencies {
    //項(xiàng)目的依賴關(guān)系
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    //本地jar包依賴
    implementation 'com.android.support:appcompat-v7:27.1.1'
    //遠(yuǎn)程依賴
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    testImplementation 'junit:junit:4.12'
    //聲明測(cè)試用例庫(kù)
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'}

Gradle 構(gòu)建生命周期

在解析 Gradle 的編譯過(guò)程之前我們需要理解在 Gradle 中非常重要的兩個(gè)對(duì)象。Project和Task。

每個(gè)項(xiàng)目的編譯至少有一個(gè) Project,一個(gè) build.gradle就代表一個(gè)project,每個(gè)project里面包含了多個(gè)task,task 里面又包含很多action,action是一個(gè)代碼塊,里面包含了需要被執(zhí)行的代碼。

在編譯過(guò)程中, Gradle 會(huì)根據(jù) build 相關(guān)文件,聚合所有的project和task,執(zhí)行task 中的 action。因?yàn)?build.gradle文件中的task非常多,先執(zhí)行哪個(gè)后執(zhí)行那個(gè)需要一種邏輯來(lái)保證。這種邏輯就是依賴邏輯,幾乎所有的Task 都需要依賴其他 task 來(lái)執(zhí)行,沒(méi)有被依賴的task 會(huì)首先被執(zhí)行。所以到最后所有的 Task 會(huì)構(gòu)成一個(gè) 有向無(wú)環(huán)圖(DAG Directed Acyclic Graph)的數(shù)據(jù)結(jié)構(gòu)。

無(wú)論什么時(shí)候執(zhí)行Gradle構(gòu)建,都會(huì)運(yùn)行3個(gè)不同的生命周期階段:初始化、配置、執(zhí)行。

  • 初始化(Initialization):Gradle為每個(gè)項(xiàng)目創(chuàng)建一個(gè)Project實(shí)例,在多項(xiàng)目構(gòu)建中,Gradle會(huì)找出哪些項(xiàng)目依賴需要參與到構(gòu)建中。
  • 配置(Configuration):執(zhí)行所有項(xiàng)目的構(gòu)建腳本,也就是執(zhí)行每個(gè)項(xiàng)目的build.gradle文件。這里需要注意的是,task里的配置代碼也會(huì)在這個(gè)階段執(zhí)行。
  • 執(zhí)行(Execution):Gradle按照依賴順序依次執(zhí)行task。

自己總結(jié)出來(lái)的gradle多模塊構(gòu)建流程:(若有錯(cuò)誤還望指出)

項(xiàng)目啟動(dòng)編譯后,會(huì)先下載gradle-wrapper.properties文件中配置的gradle版本,若已經(jīng)下載就不需要下載了;然后去加載Setting文件,將其中指定的所有module全列入編譯;最后從根gradle文件開始配置,編譯。

引用博客:

gradle學(xué)習(xí)系列文章
史上最全Android build.gradle配置詳解
Gradle在Android工程中的運(yùn)用
重要-作為Android開發(fā)者必須了解的Gradle知識(shí)
Android Gradle 完整指南

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 在 Android Studio 構(gòu)建的項(xiàng)目中,基于 Gradle 進(jìn)行項(xiàng)目的構(gòu)建,同時(shí)使用 Android DS...
    Ant_way閱讀 7,413評(píng)論 0 16
  • Gradle是一個(gè)框架,它定義了一套自己的游戲規(guī)則。 首先介紹Gradle中的基本組件: Gradle中每一個(gè)待編...
    我是吸血鬼閱讀 828評(píng)論 0 2
  • Gradle是基于動(dòng)態(tài)語(yǔ)言而非XML的構(gòu)建系統(tǒng)。它有約定優(yōu)先于配置的原則,即為設(shè)定提供默認(rèn)值。 項(xiàng)目:每次構(gòu)建都至...
    chym閱讀 625評(píng)論 0 0
  • 什么是gradle Gradle 是新一代的自動(dòng)化構(gòu)建工具,它是一個(gè)獨(dú)立的項(xiàng)目,跟 AS、Android 無(wú)關(guān),官...
    Boreas_su閱讀 4,356評(píng)論 0 5
  • 說(shuō)明 本文主要介紹和Gradle關(guān)系密切、相對(duì)不容易理解的配置,偏重概念介紹。部分內(nèi)容是Android特有的(例如...
    jzj1993閱讀 15,716評(píng)論 1 62