Gradle task
本文來自網易雲社群
作者:ofollow,noindex">孫有軍
1:gradle指令碼是使用groovy語言寫的(DSL),groovy中有一個重要的概念閉包(Closure),Closure是一段單獨的程式碼塊,它可以接收引數,返回值,也可以被賦值給變數。eg:
//無引數def Closure1 = { println 'Hello world' } Closure1()// 執行閉包,輸出Hello world//一個引數def Closure2 = { String str -> println str }//如果只有一個引數可以用it代替,寫作def Closure2 = {println it}Closure2('Hello world')// 執行閉包,輸出Hello world//多個引數def Closure3 = { String str,int n -> println “$str : $n" }//也可以寫作 {str,n -> println “$str : $n" } Closure3('Hello world’, 1)// 執行閉包,輸出Hello world : 1 //使用變數 def var=“Hello world" def Closure4 = { println var }//也可以寫作 {str,n -> println “$str : $n" } Closure4()// 執行閉包,輸出Hello world //改變上下文 def Closure5 = {println Var} //這時還不存在 MyClass m = new MyClass() Closure5.setDelegate(m)// 改變上下文,這時Var已經有了,在執行之前改變了, Closure5()//執行閉包,輸出Hello world class MyClass { def Var = 'Hello world' }
把closure當做引數傳遞 closure的好處就是可以傳遞給不同的方法,這樣可以幫助我們解耦執行邏輯。前面的例子中已經展示瞭如何把closure傳遞給一個類的例項。下面我們將看一下各種接收closure作為引數的方法:
1.只接收一個引數,且引數是closure的方法: myMethod(myClosure) 2.如果方法只接收一個引數,括號可以省略: myMethod myClosure 3.可以使用內聯的closure: myMethod {println ‘Hello World’} 4.接收兩個引數的方法: myMethod(arg1, myClosure) 5.和4類似,單數closure是內聯的: myMethod(arg1, { println ‘Hello World’ }) 6.如果最後一個引數是closure,它可以從小括號從拿出來: myMethod(arg1) { println‘Hello World’ }
-
Android中使用
buildscript { //等同 def buildscript(Closure closure),?? buildscript直接使用,那是在什麼地方定義的? repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:1.2.3' } }
方法都是在Project中定義的,構建指令碼頂層的語句塊都會被委託給Project的例項,eg: 在Project中buildcript的定義:
/** * <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);
上面可以看到repositories在ScriptHandler中執行,在ScriptHandler中又委託到RepositoryHandler。
3: task 有兩個生命週期,配置階段和執行階段,gradle在執行task時,都會先對task進行配置,task中最頂層的程式碼就是配置程式碼,在配置階段執行,其他程式碼實在執行階段執行的。eg:
task Task1{println “hello” // 這段程式碼是在gradle配置階段執行的} task Task2{ def name =“hello”// 這段程式碼是在gradle配置階段執行的doLast{println name // 這段程式碼是在gradle執行階段執行的} } task Task3 << {// << 語法糖,相當於doLast,因此整個程式碼都是在執行階段執行的println name // 這段程式碼是在gradle執行階段執行的}
4:task執行順序 dependsOn: TaskB 依賴TaskA, TaskB.dependsOn TaskA 這樣每次執行B都會先執行A,下面是相同的寫法
task A << {println 'Hello from A'} task B {dependsOn A doLast {println 'Hello from B' } }
同理也可以改變已有的依賴順序,直接改變dependsOn,也可以同時依賴多個任務。
mustRunAfter: 有A B C三個task, C依賴於A,B,但A,B不相互依賴,如果要保證每次執行時A都在B之前執行,可以寫作
task A << {println 'A'} task B << {println 'B'} task C << {println 'C'} C.dependsOn A C.dependsOn B B.mustRunAfter A
finalizedBy:現在有兩個task,unit和ui,假定這兩個task都會輸出測試報告,把這兩個測試報告合併成一個:
task unit << {println 'Hello from unit tests'} task ui << {println 'Hello from UI tests'} task tests << {println 'Hello from all tests!'} task mergeReports << {println 'Merging test reports'} tests.dependsOn unit tests.dependsOn ui ui.mustRunAfter unit mergeReports.dependsOn tests // 執行這個就可以合併了。// 下面這種方式等價於上面這種tests.dependsOn unit tests.dependsOn ui ui.mustRunAfter unit mergeReports.dependsOn tests
tests.finalizedBy mergeReports// 執行tests就能合併了。表示tests執行完成後,在執行mergeReports
網易雲 免費體驗館 ,0成本體驗20+款雲產品!
更多網易研發、產品、運營經驗分享請訪問 網易雲社群 。