麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發設計 > 正文

4gradle基礎概念

2019-11-09 15:44:10
字體:
來源:轉載
供稿:網友

gradle基礎概念

本文以前文寫的Posdevice和Version2Asset這2個工程為例說說gradle基礎概念,主要介紹delegate、sb、常見task以及如何插入task。

gradle是配置型腳本,每個gradle文件的存在意義就是配置某個對象,一個gradle文件執行的時候,會配置一個對象。比如build.gradle會配置一個PRoject對象,我們稱這個build.gradle的委托對象。腳本(gradle文件)和委托對象的對照表如下:

Type of script Delegates to instance of 對應文件
Build script Project build.gradle
Init script Gradle
Settings script Settings setting.gradle

在腳本里可以用委托對象的方法或者屬性,這句話怎么理解?舉個例子

//root build.gradle// Top-level build file where you can add configuration options common to all sub-projects/modules.println "root build.gradle execute"buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.2.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files }}subprojects{//為每個子 Project 加載 utils.gradle 。當然,這句話必須位于subprojects之內 apply from: rootProject.getRootDir().getAbsolutePath() + "/utils.gradle"}allprojects { repositories { jcenter() }}task clean(type: Delete) { delete rootProject.buildDir}

在上邊的代碼里,實際上我們可以看到腳本里的東西有3種類型,第一種是L3 println開頭的語句(groovy代碼結尾不需要加分號);第二種是buildscript,subprojects,allprojects這3個大括號形式的東西(后面我們會知道他們叫script block);第三種是定義了一個clean的task。 實際上buildscript、subprojects、allprojects都是Project類(org.gradle.api. Project)的方法,這就是在腳本里可以用委托對象的方法或者屬性,在這里腳本就是build.gradle文件,而腳本的委托對象是一個Project對象,所以我們可以在腳本里使用Project的類或者方法。 我也挺震驚的,buildscript、subprojects、allprojects居然是方法,我之前一直以為是腳本就這么配置的,記住就行。 實際上buildscript的完全體應該是如下,buildscript接收閉包參數,而閉包就是這個{},groovy的語法規定,如果只有一個參數是閉包,那么可以省略(),所以就變成了上文的樣子。實際上這段代碼的意思是執行buildscript函數,跟我們執行println是類似的,都是方法執行。

buildscript ({ repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.2.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files }})

gradle給這種類型的方法起了個新名字叫做script block,script block是gradle里的一個非常重要的概念.

A script block is a method call which takes a closure as a parameter

實際上下面這段代碼也是函數調用,調用了一個task的函數,最后一個參數為閉包。

task clean(type: Delete) { delete rootProject.buildDir}

script block delegate

我們看到build.gradle內有script block(簡稱sb),buildscript{。。。}和subprojects{。。。},是不是都是project來執行這2個sb呢?不對。我們知道閉包有delegate的概念,給閉包設置delegate,就能讓閉包的執行主體改變。這里正是如此,buildscript內閉包的delegate是一個ScriptHandler。可以看buildscript的注釋,如下所示,注意against this project's {@link ScriptHandler},這就是指定delegate的意思。同理subprojects函數的閉包參數的target是當前project的子project,其實就是2個subproject.

/** * <p>Configures the build script classpath for this project. * * <p>The given closure is executed against this project's {@link ScriptHandler}. The {@link ScriptHandler} is * passed to the closure as the closure's delegate. * * @param configureClosure the closure to use to configure the build script classpath. */ void buildscript(Closure configureClosure);

build.gradle下的可配sb

Block Description
allprojects { } Configures this project and each of its sub-projects.
artifacts { } Configures the published artifacts for this project.
buildscript { } Configures the build script classpath for this project.
configurations { } Configures the dependency configurations for this project.
dependencies { } Configures the dependencies for this project.
repositories { } Configures the repositories for this project.
sourceSets { } Configures the source sets of this project.
subprojects { } Configures the sub-projects of this project.
publishing { } Configures the PublishingExtension added by the publishing plugin.

注意subprojects和allprojects的區別,allprojects=subprojects+root project

android-gradle-plugin

這個時候有個問題,我們發現build.gradle支持的sb下并沒有android{},那為什么下邊的build.gradle里有android{},原因是我們引入了com.android.application這個插件。那android內閉包的delegate是什么呢?看官方文檔可知,app插件會讓閉包的delegate為AppExtension。

apply plugin: 'com.android.application'println 'app build.gradle execute'android {// 采用api導入的方式 compileSdkVersion gradle.api// 利用gradle.properties buildToolsVersion buildToolsVer defaultConfig { applicationId "com.fish.posdevice" minSdkVersion 15 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } }}dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.0.1' testCompile 'junit:junit:4.12' compile project(':cposdevicesdk')}

所以在andorid內,我們可以用哪些sb,就看AppExtension支持什么。看到了熟悉的aapt,dex, signingConfigs

Block Description
aaptOptions { } Configures aapt options.
adbOptions { } Configures adb options.
buildTypes { } Configures build types.
compileOptions { } Configures compile options.
dataBinding { } Configures data binding options.
defaultConfig { } The default configuration, inherited by all product flavors (if any are defined).
dexOptions { } Configures dex options.
externalNativeBuild { } Configures external native build options.
jacoco { } Configures JaCoCo options.
lintOptions { } Configures lint options.
packagingOptions { } Configures packaging options.
productFlavors { } Configures product flavors.
signingConfigs { } Configures signing configs.
sourceSets { } Configures source sets.
splits { } Configures APK splits.
testOptions { } Configures test options.

如何查某個sb內支持哪些屬性和方法

比如下邊這段代碼,我們怎么知道buildTypes里面可以配置minifyEnabled,proguardFiles,signingConfig。首先我們要看buildTypes這個方法的delegate,查官方文檔可知buildTypes的delegate是BuildType,而看BuildType可知他支持minifyEnabled,proguardFiles,signingConfig等屬性,所以我們才能在這里這么配置

buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } demo { //和debug使用同一個簽名 signingConfig signingConfigs.debug } }

gradle生命周期

對應module LifeCycle。這是一個有一個app,一個lib的android studio工程的gradle構建的基本流程。

x-Pro:LifeCycle fish$ ./gradlew assemble -qsetting.gradle execute begin...setting.gradle execute finish...root build.gradle execute begin...root build.gradle execute end...app build.gradle execute begin...app build.gradle execute end...app afterProject appapp beforeProject mylibrarylib build.gradle execute begin...lib build.gradle execute end...app afterProject mylibrarytaskGraph.whenReady。。。執行taskapp buildFinished

常見task

assemble The task to assemble the output(s) of the project. 生成所有產物,一般來說assemble依賴于assembleDebug、assembleDebug及assembleXXX(XXX為自己定義的type)check The task to run all the checks.build This task does both assemble and check. build依賴于assemble和checkclean This task cleans the output of the project,刪掉所有構建產物

我一般常用asemble/asembleDebug/clean.

build,assemble,clean build可切換, build variant

task依賴關系

初學gradle時,很想知道各個任務之間的依賴關系,但是發現沒什么人提到這個,后來我明白,原來是android gradle插件太復雜了,隨隨便便一兩百個任務。看task依賴關系,可以用visteg插件,比較好,能夠圖形化展示依賴關系

visteg插件

使用visteg插件很簡單,只要在root的build.gradle下加以下代碼就好了

buildscript { repositories { jcenter() } dependencies { classpath 'cz.malohlava:visteg:1.0.0' }}apply plugin: 'cz.malohlava.visteg'visteg { enabled = true colouredNodes = true colouredEdges = true destination = 'build/reports/visteg.dot' exporter = 'dot' colorscheme = 'spectral11' nodeShape = 'box' startNodeShape = 'hexagon' endNodeShape = 'doubleoctagon'}

然后我們執行./gradlew build就會生成dot文件,位于build/reports/,這個文件里記載了依賴關系。

怎么看這個dot文件呢?需要graphviz,可以用homebrew裝上graphviz brew install graphviz 然后執行下邊的命令就可以了,把dot轉化為png,看png就好了。

cd build/reports/dot -Tpng ./visteg.dot -o ./visteg.dot.png

此時我們得到了一個png圖,一個dot文件,2者對照著看,task依賴關系就很清晰了。

visteg的github地址https://github.com/mmalohlava/gradle-visteg

常見task依賴關系

以Version2Asset為例,這是個單module工程。

assemble依賴于assembleDebug, assembleRelease, assembleDemoassembleDebug依賴于compileDebugSources,packageDebugas的build—>make project是執行compileDebugSources、compileDebugAndroidTestSources(注意assmbleDebug不會執行compileDebugAndroidTestSources)as的build—>rebuild project是執行clean、compileDebugSources、compileDebugAndroidTestSources

as內build—>make project后可以在message里看到如下信息,這就是make project執行的task,看著很多,其實核心就是compileDebugSources和compileDebugAndroidTestSources。

Information:Gradle tasks [:app:generateDebugSources, :app:generateDebugAndroidTestSources, :app:mockableAndroidJar, :app:prepareDebugUnitTestDependencies, :app:compileDebugSources, :app:compileDebugAndroidTestSources, :app:compileDebugUnitTestSources]

而rebuild project會多執行一個clean

插入task

我們寫自己的構建代碼的時候常常要在原有task的基礎上插入一些自己的task,如何插入呢?

在2個task之間插入

task之間的依賴關系都是通過dependson這個函數形成的。 B.dependsOn A 是把A加到B的依賴集(一個set)里去,并不是說B只依賴于A,他很可能還依賴于很多task。同時A也可能被很多人依賴,所有的task之間是一個有向圖的關系。一個task可以被多次依賴,但不會多次執行。 我們為了自己的構建需求經常需要插入自己的task,如何插呢? 比如,已知clean->b,我想插一個iamc,即clean->c->b,怎么做? 代碼如下

task b<<{ println 'task bb'}task c<<{ println 'task cc'}clean.dependsOn 'b'project.afterEvaluate {// insert task between clean and 'b' clean.dependsOn(c) c.dependsOn(b)}

其實,此時clean->c,b 但是c->b,所以b肯定先執行,而且只執行一次,所以我們可以寫clean->c->b。

task的執行順序可以看這篇文章,譯文是這里

在某個task之前插入task

比如task clean->some tasks,我們不想知道some tasks是哪些task,我們只是想在clean和some tasks之間插入一個c,怎么做?可以先查到ome tasks,然后讓clean-》c,c->some tasks,代碼如下(local project:TaskInsert)

void copyDependsOn(Task base, Task task) { for (Object depend : base.dependsOn) { task.dependsOn(depend) }}task b<<{ println 'task bb'}task c<<{ println 'task cc'}clean.dependsOn 'b'project.afterEvaluate {// insert task before clean copyDependsOn(clean, c) clean.dependsOn(c)}

在某個task之前插代碼

在某個task之前插代碼還可以用doFirst,來操作,如下,在clean之前加代碼。doFirst實際上是往一個task的actionList內加一個閉包,并且放在頭部。

clean.doFirst{ println 'clean first'}

根據類型來找task,并設置依賴關系

比如下邊就是找到javaCompile類型的task,并且給這個task設置依賴關系。這樣在compileTask執行前,必定會執行abc

task abc<<{ println 'abc'}tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn abc}

總結

通過這篇文章知道了,哪些sb可以寫在build.gradle里,哪些sb可以寫在android內部。常見的task,task之間的依賴關系,以及如何插入task。

Ref

https://docs.gradle.org/current/dsl/index.html http://tools.android.com/tech-docs/new-build-system/user-guide http://stackoverflow.com/questions/20375863/difference-between-make-and-build-in-android-studio

Uncle Chen的gradle系列文章,寫的不錯


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 狠狠干夜夜草 | 一区二区三区欧美日韩 | 天堂二区 | 九色91视频| 欧美国产一区二区三区 | 五月天堂婷婷 | 免费在线性爱视频 | 精品亚洲在线 | 真人一级毛片免费 | 性欧美在线视频 | 国产精品视频亚洲 | 一级黄色性感片 | 久久嗨 | 免费一级毛片在线播放视频 | 精品中文字幕在线观看 | 国产精品视频成人 | 久久久久久久一区二区 | 欧美日韩专区国产精品 | 国产美女视频免费 | 中文字幕欧美日韩 | 8x成人在线电影 | 久草导航 | 青青青在线免费 | 一级黄色免费 | 国产精品亚洲综合一区二区三区 | 亚洲第一精品在线 | 男男羞羞视频网站国产 | 草逼一区 | 欧美激情性色生活片在线观看 | 亚洲三区精品 | 国产一区二区三区视频观看 | 久久久日韩av免费观看下载 | 香蕉视频h | 免费黄网站在线播放 | 国产成人精品无人区一区 | 国产精品久久久久久久久久大牛 | 国产成人精品免高潮在线观看 | 日韩精品网站在线观看 | 在线中文字幕播放 | 精品国产一级毛片 | 国产外围在线 |