Gradle Tips#2-構文

6104 ワード

最初のブログでは、tasksと構築過程におけるtaskの異なる段階について説明しました.この文章を書いた後、Gradleをもっと詳しく話すべきだと気づきました.複雑な構築スクリプトに遭遇したときに直接料理に酔わないように、文法を理解することが重要です.この文章は文法的なことを説明します.
構文
GradleスクリプトはGroovy言語で書かれています.Groovyの文法はJavaに似ていますので、それを受け入れてほしいです.Groovyに詳しいなら、この部分をスキップしてもいいです.Groovyには重要な概念があります-Closure(閉パッケージ)
Closures
Closureは私たちがGradleを理解する鍵です.Closureは、パラメータを受信したり、値を返したり、変数に値を付与したりする個別のコードブロックです.JavaのCallableインタフェースと似ていて、Futureも似ていて、関数ポインタのように、あなた自身がどのように便利に理解してもいいです.の
重要なのは、このコードが作成されたときではなく、呼び出されたときに実行されることです.Closureの例を見てみましょう
def myClosure = { println 'Hello world!' }

//execute our closuremy
Closure()

#output: Hello world!

次に、パラメータを受信するClosureを示します.
def myClosure = {String str -> println str }

//execute our closuremy
Closure('Hello world!')

#output: Hello world!

Closureが1つのパラメータしか受信していない場合は、itを使用してこのパラメータを参照します.
def myClosure = {println it }

//execute our closuremy
Closure('Hello world!')

#output: Hello world!

複数のパラメータを受信するClosure:
def myClosure = {String str, int num -> println "$str : $num" }

//execute our closure
myClosure('my string', 21)

#output: my string : 21

また、パラメータのタイプはオプションで、上記の例は以下のように簡単に書くことができます.
def myClosure = {str, num -> println "$str : $num" }

//execute our closure
myClosure('my string', 21)

#output: my string : 21

クールなのは、Closureで現在のコンテキストの変数を使用できることです.デフォルトでは、現在のコンテキストはclosureが作成されたときのクラスです.
def myVar = 'Hello World!'
def myClosure = {println myVar}
myClosure()

#output: Hello world!

もう1つのクールな点はclosureのコンテキストが変更可能であり、Closure#setDelegate()を介している.この機能は非常に役立ちます.
def myClosure = {println myVar} //I'm referencing myVar from MyClass class
MyClass m = new MyClass()
myClosure.setDelegate(m)
myClosure()

class MyClass {
    def myVar = 'Hello from MyClass!'
}

#output: Hello from MyClass!

ご覧のように、closureを作成するときはmyVarは存在しません.これは、closureを実行するときにclosureのコンテキストにmyVarが存在するため、問題はありません.この例では.closureを実行する前にコンテキストをmに変更したのでmyVarは存在します.
closureをパラメータとして渡す
closureの利点は、実行ロジックをデカップリングするのに役立つように、異なる方法に伝えることです.前の例ではclosureをクラスに渡す方法を示した.次に、パラメータとしてclosureを受信する方法について説明します.
1.1つのパラメータのみを受信し、パラメータがclosureの方法:myMethod(myClosure)2.メソッドが1つのパラメータしか受信していない場合、カッコは省略できます:myMethod myClosure 3.インラインclosure:myMethod{println'Hello World}4を使用できます.2つのパラメータを受信する方法:myMethod(arg 1,myClosure)5.4と同様に、単数closureはインラインである:myMethod(arg 1,{println‘Hello World’})6.最後のパラメータがclosureの場合、myMethod(arg 1){println‘Hello World’}という括弧から取り出すことができます.
ここで注意したいのは、3と6の書き方が見覚えがあるように見えますか?
Gradle
基本的な構文を理解しましたが、Gradleスクリプトでどのように使用しますか?まず次の例を見てみましょう.
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.2.3'
    }}

allprojects {
    repositories {
        jcenter()
    }
}

Groovyの文法を知って、上の例が分かりやすいのではないでしょうか.まず、closureを受信するbuildscriptメソッドです.
def buildscript(Closure closure)

次にallprojectsメソッドです.closureパラメータも受信します.
def allprojects(Closure closure)

他は似ています...
今はずっと簡単に見えますが、これらの方法がどこで定義されているのか少し分かりません.結果はプロジェクト
Project
これはGradleスクリプトを理解する鍵です.
構築スクリプトの最上位レベルの文ブロックがプロジェクトのインスタンスに委任されます
これはプロジェクトが私が探している場所であることを示しています.Projectのドキュメントページでbuildscriptメソッドを検索すると、buildscript{}script block(フッターブロック)が見つかります.待って、script blockは何ですか?ドキュメントに基づいて:
script blockはclosureのみをパラメータとして受信する方法です
buildscriptのドキュメントを読み続け、Delegates to:ScriptHandler from buildscriptと言います.すなわち,buildscriptメソッドのclosureに渡され,最終的に実行されるコンテキストはScriptHandlerである.上記の例では、buildscriptに渡されるclosureは、repositories(closure)およびdependencies(closure)メソッドを呼び出します.closureがScriptHandlerに依頼された以上、ScriptHandlerでdependenciesメソッドを探します.
void dependencies(Closure configureClosure)が見つかりました.ドキュメントによると、dependenciesはスクリプトの依存性を構成するために使用されます.dependenciesは最終的にDependencyHandlerに依頼した.
Gradlesがどんなに広く使われているかを見たことがあるでしょう.依頼を理解することが大切です.
Script blocks
デフォルトでは、Projectではscript blockがたくさん定義されていますが、Gradleプラグインでは新しいscript blocksを自分で定義できます!これは、buildスクリプトの最上位レベルで{...}を送った場合、Gradleのドキュメントにこのscript blocksやメソッドが見つかりません.ほとんどの場合、これはプラグインで定義されたscript blockから来ています.
android Script block
デフォルトのAndroidアプリ/buildを見てみましょう.gradleファイル:
apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "com.trickyandroid.testapp"
        minSdkVersion 16
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

ここにはclosureパラメータを受信するandroidメソッドがあることがわかります.しかし、プロジェクトのドキュメントで検索すると、この方法は見つかりません.理由は簡単で、プロジェクトで定義された方法ではありません. 
buildスクリプトをよく見るとandroidメソッドを相殺する前にcomを使用していたことがわかります.android.アプリケーションプラグイン.AndroidアプリケーションプラグインはProjectオブジェクトを拡張し、android Script blockを追加しました.Androidプラグインのドキュメントはどこで見つけられますか?Android Tools websiteかここ
AppExtensionのドキュメントを開くと、build scriptで使用する方法とプロパティを見つけることができます:1.compileSdkVersion 22. compileSdkValersonを検索すると、このプロパティが表示されます.ここでは、この属性に「22」を割り当てます. 2.buildToolsVersionは1と類似している.defaultConfig-script blockはProductFlavorクラスに委任されて実行されます. 4.他にもGradleスクリプトの構文が理解でき、ドキュメントの検索方法もわかりました.
練習する
何かを配置して手を練習しましょう.AppExtensionでscript block testOptionsを探しました.closureパラメータをTestOptionsクラスに委任します.ドキュメントによると、TestOptionsクラスにはreportDirとresultsDirの2つのプロパティがあります.ReportDirはtestレポートを保存するために使用されます.この属性を変更してみましょう.
android {......
    testOptions {
        reportDir "$rootDir/test_reports"
    }
}

ここではプロジェクトで定義したrootDirプロパティを使用します.このプロパティ値はプロジェクトのルートディレクトリです.もし私が実行したら./gradlew connectedCheck、testレポートは[rootProject]/test_に保存されます.Reportsディレクトリにあります.実際のプロジェクトでこの修正を試みないでください.すべての構築出力はbuildディレクトリにあるはずです.そうすれば、プロジェクトディレクトリ構造を汚染することはありません.