Android 開発のための Gradle の基本

Android Studio プロジェクトのプロジェクト構造

プロフェッショナルな Android 開発ツールとして、Android Studio は Android プロジェクトを構築する際に大きな利点があります。まず、Android のプロジェクト構造を理解することが非常に重要です。写真のすぐ上: 実際、完全な Android Studio プロジェクトは次のように分割できます
Android Studio によって生成されるプロジェクト構造
。 5 図で選択した部分は、日常生活で頻繁に開発され、注目される部分です。

  • app モジュール: Android プロジェクトのコア モジュールです。プロジェクトのコア機能と主要な業務は、このモジュールの下で開発されます。ビルド フォルダーには、コンパイルによって生成されたファイルが保存されます。build.gradle は、このモジュールの構築スクリプトです
  • 図のパート 2: プロジェクト全体のビルド スクリプト (build.gradle)、プロジェクトの基本構成情報 (settings.gradle)、build.gradle を中心とした実行スクリプトおよびいくつかの構成ファイル
  • 図の3部:Gradleのバージョンとキャッシュパスの構成情報
  • 図のパート 4: プロジェクトのサブモジュール。構造はアプリに似ています

Gradle の概要

Gradle は、Apache Ant と Apache Maven の概念に基づいてプロジェクト自動化を構築するためのオープンソース ツールです。Groovyベースのドメイン固有言語 ( DSL )を使用してプロジェクト設定を宣言し、Kotlin 言語に基づく kotlin ベースの DSL も追加して、XML に基づくさまざまな煩雑な構成を放棄します。

Gradle では、スクリプト開発に Groovy または Kotlin 言語を使用できます。現在、主に Groovy 言語が使用されています。ここでは Groovy 構文については説明しません。クロージャーとその動的特性に焦点を当てます。

インストールチュートリアルやその他のコンテンツはオンラインで科学的に閲覧できます~~

Gradle タスク - タスク

タスクは Gardle における最小のタスク単位であり、タスク間で複雑な操作(タスクの動的作成、複数タスク間の相互依存呼び出しなど)を実行できます。gradle の実行は、実際にはプロジェクトを構築するためのさまざまなタスクの組み合わせによって実行されます。

gradlew helpコマンドを使用すると、どの Gradle プロジェクトにもこのタスクがあり、このコマンドを実行して、taks の実行プロセスが期待どおりであるかどうかを観察できます。

ツールを使用して表示することも、gradlew taskコマンドを使用して実行可能なタスクを表示することもできます。

すべてのタスクを表示するには、 gradlew task --allコマンドを使用します

gradlew ABコマンドを使用してタスク A および B を実行し、キャメルケースの省略形をサポートします。

単純な Android プロジェクトを作成し、アプリの下の build.gradle に単純なタスクを記述してみます。
ここに画像の説明を挿入
緑色の三角形をクリックしてタスクを実行するか、コマンド ラインを使用して実行できます。コマンド ラインの実行は次のとおりです。 1 つを選択します。出力はコンソールに表示されます。

D:\TestCode\GeadleLearning>gradlew pH

D:\TestCode\GeadleLearning>gradlew printHello

ここに画像の説明を挿入
タスクに関するその他の機能

task A {
    
    
    doLast {
    
    
        println "doLast A ..."
    }
}

task C {
    
    
    doLast {
    
    
        println "doLast C ..."
    }
}

task B {
    
    
    doLast {
    
    
        println "doLast B ..."
    }
}
// hello 任务依赖于A、B、C三个任务,按照Gradle任务列表中的顺序进行执行
task hello(dependsOn: [A, C, B]) {
    
    
    //任务执行的时候首先执行该闭包
    doFirst {
    
    
        println "doFirst hello start..."
    }

    //任务执行到最后执行该闭包
    doLast {
    
    
        println "doLast hello end..."
    }
}

//指定依赖关系,任务A依赖于任务C,再运行任务A之前先运行任务C
A.dependsOn C

//A必须运行再B运行之后
A.mustRunAfter B

task finalized {
    
    
    doLast {
    
    
        println "清理一些资源"
    }
}

//通过自定义任务类来实现任务
class MyTask extends DefaultTask {
    
    
    @Input
    String filePath

    @OutputFile
    File outFile

    //指定任务所在的分组
    MyTask() {
    
    
        group "自定义任务"
        description "我是一个自定义任务"
    }

    @TaskAction
    void runAction1() {
    
    
        println "MyTask runAction1"
    }

    @TaskAction
    void runAction2() {
    
    
        println "MyTask runAction2"
    }

    void sayHello(String str) {
    
    
        println str
    }
}

//创建名为myTask类型为MyTask的任务
tasks.create("myTask", MyTask)

ここに画像の説明を挿入

ジードル実行プロセス

画像はインターネットから来ました

Gradleフック機能

Gradle はライフサイクルの各段階で独自のフック関数を設定し、開発者はこれらの関数をカスタム構築に使用できます。

初期化フェーズ: gradle.settingsEvaluated および gradle.projectsLoaded。(settings.gradleで有効になります)

構成フェーズ: project.beforeEvaluate および project.afterEvaluate、gradle.beforeProject、gradle.afterProject および gradle.taskGraph.taskGraph.whenReady。

実行フェーズ: gradle.taskGraph.beforeTask および gradle.taskGraph.afterTask。

/**
 * Gradle 钩子函数
 * 1、初始化阶段---->settings.gradle文件
 * 2、配置阶段,对于的其实就是build.gradle文件
 */
//gradle 针对所有项目的配置阶段
gradle.beforeProject {
    
    
    println "gradle.beforeProject"
}
gradle.afterProject {
    
    
    println "gradle.afterProject"
}
gradle.taskGraph.whenReady {
    
    
    println "gradle.taskGraph.whenReady"
}
//project只针对当前Module生效
project.beforeEvaluate {
    
    
    //在root中无效
    println "app.project.beforeEvaluate"
}
project.afterEvaluate {
    
    
    println "app.project.afterEvaluate"
}

さらに、Geadle オブジェクトのリスナーを設定することもできます

gradle.addProjectEvaluationListener(new ProjectEvaluationListener() {
    
    
    @Override
    void beforeEvaluate(Project project) {
    
    
        //如果是在Module的build.gradle中并不会执行该方法
        println "beforeEvaluate(Project project)"
    }

    @Override
    void afterEvaluate(Project project, ProjectState projectState) {
    
    
        println "afterEvaluate(Project project, ProjectState projectState)"
    }
})

gradle.addBuildListener(new BuildListener() {
    
    
    @Override
    void settingsEvaluated(Settings settings) {
    
    
        println "初始化阶段"
    }

    @Override
    void projectsLoaded(Gradle gradle) {
    
    
        println "加载阶段"
    }

    @Override
    void projectsEvaluated(Gradle gradle) {
    
    
        println "配置阶段"
    }

    @Override
    void buildFinished(BuildResult buildResult) {
    
    
        println "构建结束时调用"
    }
})

Gradleの依存関係管理

複雑な機能を持つ Android プロジェクトでは、多くのサードパーティ SDK とモジュール管理が存在することがよくありますが、これらの複雑な SDK の依存関係やモジュール間の依存関係において Gradle は重要な役割を果たします。

プロジェクトの下の build.gradle

プロジェクト全体の build.gradle では、AndroidStudio の下位バージョンでは、プロジェクトのビルド時にプロジェクトの構築に関するいくつかのプラグインがこのスクリプトに追加されます。

//低版本AS创建的项目在build.gradle文件中添加插件的依赖
dependencies {
    
    
    classpath 'com.android.tools.build:gradle:7.1.2'
    classpath 'org.greenrobot:greendao-gradle-plugin:3.2.0'
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
// Top-level build file where you can add configuration options common to all sub-projects/modules.
//顶级构建文件,您可以在其中添加所有子项目/模块通用的配置选项(AS版本:Electric Eel | 2022.1.1 Patch 1)
plugins {
    
    
    id 'com.android.application' version '7.1.2' apply false
    id 'com.android.library' version '7.1.2' apply false
    id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
}

新しいバージョンではプラグインのバージョンが指定されておらず、明示的にプラグインが追加されていないことがわかります。AS に統合されている可能性があります。公式ドキュメントと Gradle ドキュメントを参照する必要があります。これはそうではありません。大したこと。

倉庫指定

Gradle は Maven と同様にウェアハウスを持っており、このようにスクリプト内でウェアハウスを指定しますが、新バージョンの AS では、指定されたウェアハウスが settings.gradle スクリプト内に配置されます。

pluginManagement {
    
    
    repositories {
    
    
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}
dependencyResolutionManagement {
    
    
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
    
    
        google()
        mavenCentral()
    }
}
rootProject.name = "GradleLearning3"
//老版本 对所有工程进行配置
allprojects {
    
    
    //为工程添加依赖仓库
    repositories {
    
    
        google()//Google的maven中央仓库
        mavenCentral()//maven中央仓库
        jcenter()//过时不维护
        maven {
    
    //从某个地址获取
        	url "xxxxxxx"
        }
    }
}
依存関係の構成

依存関係コード ブロックでは、ライブラリの依存関係を宣言するために、さまざまな依存関係構成を選択できます。それぞれの依存関係には、異なる特性があります。詳細については、依存関係構成に関する Google のドキュメントを参照してください。ここではインターセプト一部を示します。

ここに画像の説明を挿入

Gradleの依存関係の最適化

Gradle を使用してプロジェクトの依存関係を管理すると、Gradle は再コンパイル時に依存関係を最適化します。たとえば、アプリ モジュールの依存関係で繰り返しライブラリに依存し、コンパイル後に依存関係を確認します。

dependencies {
    
    
    implementation 'androidx.core:core-ktx:1.7.0'
    
    //重复导入一个库的不同版本,是否会发生依赖冲突呢???
    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'androidx.appcompat:appcompat:1.4.0'
    implementation 'androidx.appcompat:appcompat:1.4.+'
    
    implementation 'com.google.android.material:material:1.5.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

コマンド gradlew :app:dependency --configuration releaseRuntimeClassPath を使用して、コンパイルされた依存関係を表示します。一般的な 3 つの状況を図で説明します。

ここに画像の説明を挿入

出力情報から繰り返し依存している androidx.appcompat:appcompat を探し、Gradle がそれをどのように処理するかを確認すると、結果は下図のようになります。最新バージョンに置き換えられ、このライブラリの最新バージョンが以前に追加されているため、両方の依存関係は無視されます。

ここに画像の説明を挿入

依存関係の競合 依存
関係の競合の本質は、同じパッケージ名とクラス名を持つ 2 つの同一のクラスが存在することですが、Java ではこれは許可されていないため、依存関係の競合が発生します。
例えば、以下のような構造の依存関係パッケージを導入しましたが、以下の赤枠内のクラスが別の依存関係に含まれている場合、依存関係の競合が発生しますが、これを解決するにはどうすればよいでしょうか。
ここに画像の説明を挿入

赤いボックス内の依存パッケージを除外する必要があるとします。それを解決するには、次の方法を選択できます。

    implementation('androidx.room:room-runtime:2.5.0') {
    
    
        exclude group: 'androidx.room', module: 'room-common'
    }

gradlew:app:dependency --configuration releaseRuntimeClassPath を使用して再度コンパイルします。以前のサブモジュールの依存関係はないため、依存関係の競合は上記の方法で解決できます。

ここに画像の説明を挿入
依存関係全体の下にある特定のグループを強制終了することもできます。そうすると、androidx.sqlite で始まるすべてのグループが消えていることがわかります。

    implementation('androidx.room:room-runtime:2.5.0') {
    
    
//        exclude group: 'androidx.room', module: 'room-common'
        exclude group:'androidx.sqlite'
    }

ここに画像の説明を挿入
すべてを除外して使用します

//在Build.gradle添加如下代码即可去掉所有依赖中模块为annotation的依赖包
configurations {
    
    
    configuration {
    
    
       all*.exclude module:"annotation"
    }
}

依存関係のバージョンの指定は必須です

//(build.gradle的根节点)
configurations.all{
    
    
    resolutionStrategy {
    
    
        //强制指定版本
        force 'androidx.appcompat:appcompat:1.1.0'
    }
}

ここに画像の説明を挿入

依存関係推移

依存関係の転送は、特定のモジュールによってインポートされたパッケージを他のモジュールで直接使用できるかどうかを制御するために使用され、主に実装と API が関係します

ABCD四个模块
A implementation  BB implementation CA不能使用C
A implementation  BB api CA可以使用C
A implementation  BB implementation  C ,C api DB可以使用DA不能使用D
A implementation  BB api  C ,C api DA可以使用D

おすすめ

転載: blog.csdn.net/weixin_42643321/article/details/128931797