Gradle-Grundlagen für die Android-Entwicklung

Projektstruktur des Android Studio-Projekts

Als professionelles Android-Entwicklungstool bietet Android Studio große Vorteile beim Erstellen von Android-Projekten. Zunächst ist es sehr wichtig, die Projektstruktur von Android zu verstehen. Direkt über dem Bild: Tatsächlich kann ein vollständiges Android Studio-Projekt in unterteilt
Von Android Studio generierte Projektstruktur
werden 5 Die in der Abbildung ausgewählten Teile sind die Teile, die im täglichen Leben häufig entwickelt und beachtet werden. Dies sind:

  • App-Modul: Es ist das Kernmodul des Android-Projekts. Die Kernfunktionen und das Hauptgeschäft des Projekts werden unter diesem Modul entwickelt. Der Build-Ordner speichert die durch Kompilierung generierten Dateien. build.gradle ist das Konstruktionsskript dieses Moduls
  • Teil 2 in der Abbildung: das Build-Skript des gesamten Projekts (build.gradle), die grundlegenden Konfigurationsinformationen des Projekts (settings.gradle), das Ausführungsskript und einige Konfigurationsdateien, wobei der Schwerpunkt auf build.gradle liegt
  • Teil 3 in der Abbildung: Gradle-Version und Konfigurationsinformationen des Cache-Pfads
  • Teil 4 in der Abbildung: Das Untermodul des Projekts, die Struktur ähnelt der App

Einführung in Gradle

Gradle ist ein Open-Source-Tool für die Projektautomatisierung, das auf den Konzepten von Apache Ant und Apache Maven basiert. Es verwendet eine Groovy -basierte domänenspezifische Sprache ( DSL ), um Projekteinstellungen zu deklarieren, und fügt außerdem eine Kotlin-basierte DSL basierend auf der Kotlin-Sprache hinzu, wodurch verschiedene umständliche Konfigurationen auf XML-Basis überflüssig werden.

Gradle kann die Sprache Groovy oder Kotlin für die Skriptentwicklung verwenden. Derzeit wird hauptsächlich die Sprache Groovy verwendet. Die Groovy-Syntax wird hier nicht beschrieben, sondern konzentriert sich nur auf Abschlüsse und ihre dynamischen Eigenschaften.

Installationsanleitungen und andere Inhalte können online wissenschaftlich durchsucht werden~~

Gradle-Aufgabe - Aufgabe

Aufgabe ist die kleinste Aufgabeneinheit in Gardle, und komplexe Vorgänge können zwischen Aufgaben ausgeführt werden (z. B. dynamisches Erstellen von Aufgaben, Abhängigkeitsaufrufe zwischen mehreren Aufgaben usw.). Die Ausführung von Gradle erfolgt tatsächlich durch eine Kombination verschiedener Aufgaben zum Aufbau des Projekts.

Verwenden Sie den Befehl gradlew help . Jedes Gradle-Projekt hat diese Aufgabe. Sie können diesen Befehl ausführen, um zu beobachten, ob der Prozess der Aufgabenausführung wie erwartet verläuft.

Sie können Tools zum Anzeigen verwenden und ausführbare Aufgaben auch über den Befehl gradlew task anzeigen.

Verwenden Sie den Befehl gradlew task --all, um alle Aufgaben anzuzeigen.

Verwenden Sie den Befehl gradlew AB , um die Aufgaben A und B auszuführen und die Abkürzung für Kamelfälle zu unterstützen.

Wir erstellen ein einfaches Android-Projekt und versuchen, eine einfache Aufgabe in build.gradle unter der App zu schreiben.
Fügen Sie hier eine Bildbeschreibung ein
Wir können auf das grüne Dreieck klicken, um die Aufgabe auszuführen, oder die Befehlszeile verwenden, um sie auszuführen. Die Befehlszeilenausführung ist wie folgt: Wählen Sie eine aus, d. h. Die Ausgabe kann in der Konsole angezeigt werden

D:\TestCode\GeadleLearning>gradlew pH

D:\TestCode\GeadleLearning>gradlew printHello

Fügen Sie hier eine Bildbeschreibung ein
Weitere Funktionen zur Aufgabe

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)

Fügen Sie hier eine Bildbeschreibung ein

Geadle-Ausführungsprozess

Das Bild stammt aus dem Internet

Gradle-Hook-Funktion

Gradle legt in jeder Lebenszyklusphase seine eigenen Hook-Funktionen fest, und Entwickler können diese Funktionen für benutzerdefinierte Konstruktionen verwenden

Initialisierungsphase : gradle.settingsEvaluated und gradle.projectsLoaded. (wird in „settings.gradle“ wirksam)

Konfigurationsphase : project.beforeEvaluate und project.afterEvaluate; gradle.beforeProject, gradle.afterProject und gradle.taskGraph.taskGraph.whenReady.

Ausführungsphase : gradle.taskGraph.beforeTask und 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"
}

Darüber hinaus können wir auch den Listener für das Geadle-Objekt festlegen

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-Abhängigkeitsmanagement

In einem Android-Projekt mit komplexen Funktionen gibt es häufig viele SDKs und modulare Verwaltung von Drittanbietern, und Gradle spielt eine wichtige Rolle bei diesen komplexen SDK-Abhängigkeiten und Abhängigkeiten zwischen Modulen, die im Folgenden vorgestellt werden. Sehen wir uns an, wie Geadle verschiedene Abhängigkeiten verwaltet .

build.gradle unter dem Projekt

In build.gradle unter dem gesamten Projekt fügt die niedrigere Version von AndroidStudio diesem Skript beim Erstellen des Projekts einige Plug-Ins zur Projektkonstruktion hinzu

//低版本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
}

Es ist ersichtlich, dass die neue Version die Version des Plug-Ins nicht angibt und das Plug-In nicht explizit hinzufügt. Es kann in AS integriert werden. Sie müssen die offizielle Dokumentation und die Gradle-Dokumentation konsultieren. Dies ist nicht der Fall eine große Sache.

Lagerbezeichnung

Da Gradle Maven ähnelt, verfügt es über ein Warehouse. Es gibt das Warehouse im Skript auf diese Weise an. In der neuen Version von AS wurde das angegebene Warehouse im Skript „settings.gradle“ platziert

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"
        }
    }
}
Abhängigkeitskonfiguration

Im Abhängigkeitscodeblock können wir verschiedene Abhängigkeitskonfigurationen auswählen, um die Abhängigkeiten der Bibliothek zu deklarieren. Jede unterschiedliche Abhängigkeit weist unterschiedliche Merkmale auf. Einzelheiten finden Sie in der Dokumentation von Google zur Abhängigkeitskonfiguration. Hier ist ein Teil des
Abfangens
Fügen Sie hier eine Bildbeschreibung ein

Gradle-Abhängigkeitsoptimierung

Wenn wir Gradle zum Verwalten von Projektabhängigkeiten verwenden, optimiert Gradle unsere Abhängigkeiten beim Neukompilieren. Beispielsweise verlassen wir uns auf wiederholte Bibliotheken in Abhängigkeiten von App-Modulen und überprüfen die Abhängigkeiten nach der Kompilierung:

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'
}

Wir verwenden den Befehl: gradlew :app:dependencies --configuration releaseRuntimeClassPath, um die kompilierten Abhängigkeiten anzuzeigen. Die drei häufigsten Situationen werden in der Abbildung erläutert:

Fügen Sie hier eine Bildbeschreibung ein

Wir suchen nach dem androidx.appcompat:appcompat, auf das wir in den Ausgabeinformationen wiederholt angewiesen sind, und sehen, wie Gradle damit umgeht. Das Ergebnis ist wie folgt: Wir können sehen, dass sowohl die niedrigere Version als auch die neueste Version durch die neueste ersetzt werden Version, und diese beiden Abhängigkeiten werden ignoriert, da die neueste Version der Bibliothek früher hinzugefügt wurde.

Fügen Sie hier eine Bildbeschreibung ein

Abhängigkeitskonflikt
Der Kern eines Abhängigkeitskonflikts besteht darin, dass es zwei identische Klassen mit demselben Paketnamen und Klassennamen gibt, was in Java nicht zulässig ist, sodass ein Abhängigkeitskonflikt entsteht.
Beispielsweise haben wir ein Abhängigkeitspaket eingeführt, dessen Struktur wie folgt aussieht: Wenn einige Klassen im roten Feld unten in einer anderen Abhängigkeit enthalten sind, liegt ein Abhängigkeitskonflikt vor. Wie lösen wir ihn?
Fügen Sie hier eine Bildbeschreibung ein

Angenommen, wir müssen die abhängigen Pakete im roten Feld ausschließen, können wir die folgenden Lösungswege wählen:

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

Verwenden Sie gradlew:app:dependencies --configuration releaseRuntimeClassPath, um erneut zu kompilieren: Es gibt keine vorherige Untermodulabhängigkeit, sodass der Abhängigkeitskonflikt mit der oben genannten Methode gelöst werden kann.

Fügen Sie hier eine Bildbeschreibung ein
Sie können auch eine bestimmte Gruppe unter der gesamten Abhängigkeit töten und feststellen, dass alle Gruppen, die mit androidx.sqlite beginnen, verschwunden sind

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

Fügen Sie hier eine Bildbeschreibung ein
Verwenden Sie „Alle ausschließen“.

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

Obligatorische Angabe einer Version einer Abhängigkeit

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

Fügen Sie hier eine Bildbeschreibung ein

Abhängigkeit transitiv

Die Abhängigkeitsübertragung wird verwendet, um zu steuern, ob das von einem bestimmten Modul importierte Paket direkt von anderen Modulen verwendet werden kann. Dies betrifft hauptsächlich Implementierung und API. Die
einfachste Erklärung lautet wie folgt:

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

Acho que você gosta

Origin blog.csdn.net/weixin_42643321/article/details/128931797
Recomendado
Clasificación