亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

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

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??梢钥碽uildscript的注釋,如下所示,注意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插件太復雜了,隨隨便便一兩百個任務??磘ask依賴關系,可以用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系列文章,寫的不錯


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美性感美女h网站在线观看免费| 亚洲国产成人精品久久| 国产精品av在线播放| 国产区精品视频| 亚洲国产精品va在线观看黑人| 亚洲精品少妇网址| 成人免费视频网址| 91沈先生在线观看| 中文字幕在线看视频国产欧美| 69久久夜色精品国产69| 欧美激情影音先锋| 欧美日韩国产精品一区二区不卡中文| 国产精品久久视频| 日韩电影中文字幕av| 国产一区二区av| 成人中文字幕+乱码+中文字幕| 欧美性猛交xxxx乱大交| 国产女同一区二区| 亚洲色图欧美制服丝袜另类第一页| 日韩天堂在线视频| 中文字幕欧美专区| 狠狠躁夜夜躁人人躁婷婷91| 欧美在线视频a| 97国产精品免费视频| 欧美一级视频免费在线观看| 国产精品久久久久久久久久久新郎| 欧美高清在线视频观看不卡| 国产精品久久久久久久久久三级| 欧美壮男野外gaytube| 日韩大陆欧美高清视频区| 国产精品视频成人| 91chinesevideo永久地址| 中文在线不卡视频| 91精品国产自产在线观看永久| 国产精品狼人色视频一区| 日韩在线中文视频| 亚洲尤物视频网| 一本色道久久88综合亚洲精品ⅰ| 日韩在线中文字| 中文字幕精品在线| 亚洲人成人99网站| 国产一区二区日韩精品欧美精品| 亚洲精品国产拍免费91在线| 欧美国产在线视频| 国产欧美精品日韩精品| 亚洲女成人图区| 激情懂色av一区av二区av| 亚洲色图50p| 91色在线视频| 色婷婷亚洲mv天堂mv在影片| 亚洲高清久久久久久| 国产色综合天天综合网| 成人性生交大片免费看视频直播| 亚洲欧洲偷拍精品| 97在线精品国自产拍中文| 国产日本欧美一区二区三区在线| 亚洲第一免费网站| 国产精品旅馆在线| 色狠狠av一区二区三区香蕉蜜桃| 中文字幕亚洲欧美| 久久久爽爽爽美女图片| 亚洲国模精品私拍| 最好看的2019年中文视频| 中文字幕精品久久久久| 久久精品成人欧美大片古装| 亚洲xxx大片| 亚洲综合色激情五月| 久久久精品视频在线观看| 亚洲图片制服诱惑| 5566日本婷婷色中文字幕97| 欧美精品激情视频| 91久久精品国产| 国产一区二区三区在线播放免费观看| 成人免费网站在线看| 国产成人一区二区三区| 午夜精品久久久99热福利| 欧美激情精品久久久久久免费印度| 欧美wwwwww| 中文字幕亚洲无线码a| 中文字幕av一区| 久久久久久国产精品| 亚洲一级免费视频| 久久久久亚洲精品国产| 久久久中精品2020中文| 粉嫩老牛aⅴ一区二区三区| 欧美精品18videosex性欧美| 一本久久综合亚洲鲁鲁| 91在线国产电影| 怡红院精品视频| 日韩av观看网址| 国产精品视频一区国模私拍| 欧美激情一区二区三区高清视频| 国产精品免费一区二区三区都可以| 欧美国产日本在线| 亚洲色图第一页| 国内精品久久久久影院 日本资源| 欧美成人sm免费视频| 欧美视频不卡中文| 久久久久久97| 久久综合网hezyo| 人体精品一二三区| 69视频在线播放| 国产精品久久视频| 日产精品久久久一区二区福利| 亚洲免费影视第一页| 欧美xxxx14xxxxx性爽| 欧美亚洲视频在线看网址| 亚洲欧美中文在线视频| 久久久久五月天| 久久九九亚洲综合| 亚洲精品国产综合区久久久久久久| 国产啪精品视频| 欧美极品美女电影一区| 亚洲精品久久7777777| 亚洲欧美日韩在线一区| 国产精品久久网| 国产自摸综合网| 黑人狂躁日本妞一区二区三区| 97超碰色婷婷| 国产精品欧美一区二区三区奶水| 亚洲人成毛片在线播放| 久久久久久亚洲精品中文字幕| 亚洲精品国产综合久久| 亚洲高清免费观看高清完整版| 欧美亚洲日本网站| 久久中国妇女中文字幕| 精品一区二区电影| 在线播放国产精品| 国产精品爽爽爽爽爽爽在线观看| 亚洲第一男人天堂| 色播久久人人爽人人爽人人片视av| 日韩免费高清在线观看| 欧美巨猛xxxx猛交黑人97人| 亚洲精品一区av在线播放| 亚洲精品成人久久久| 精品国产一区二区三区久久狼黑人| 久久久久久久久久婷婷| 热久久视久久精品18亚洲精品| 中文字幕欧美日韩va免费视频| 久久理论片午夜琪琪电影网| 亚洲精品电影在线| 欧美孕妇与黑人孕交| 91九色视频在线| 国产精品久在线观看| 亚洲成年人在线播放| 国产精品久久久久久久电影| 亚洲欧美日韩天堂一区二区| 国产91在线高潮白浆在线观看| 福利一区视频在线观看| 亚洲精品www久久久久久广东| 成人免费视频网址| 7777精品久久久久久| yellow中文字幕久久| 欧美激情区在线播放| 久久人91精品久久久久久不卡| 欧洲日本亚洲国产区| 色噜噜狠狠狠综合曰曰曰| 日本视频久久久| 亚洲欧洲偷拍精品| 国产亚洲欧美视频| 人体精品一二三区| 成人福利网站在线观看11| 久久久久久久影视| 久久精品国产2020观看福利|