赞
踩
Android Studio作为专业的安卓开发工具,它在构建安卓项目的时候具有很大的优势,首先了解安卓的项目结构对开发非常重要,直接上图:
其实,一个完整的Android Studio工程我们可以分为5个部分,图中选出的是日常经常开发关注的部分,他们分别是:
Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,也增加了基于Kotlin语言的kotlin-based DSL,抛弃了基于XML的各种繁琐配置。
Gradle可以使用groovy或者Kotlin语言进行脚本开发,目前主要使用Groovy语言,Groovy语法此处不过多叙述,关注闭包以及他的动态特性即可。
安装教程以及其它内容可自行科学上网~~
task是gardle中最小的任务单元,任务之间可以进行复杂的操作(如动态创建任务,多任务间依赖调用等等)。gradle的执行其实就是由各种任务组合执行,来对项目进行构建的。
使用gradlew help命令,任何gradle项目都有一个该task,可以执行此命令观察taks执行的流程是否如预期。
可以使用工具查看,还可以通过 gradlew tasks 命令查看可运行任务。
使用gradlew tasks --all 命令查看所有任务。
使用gradlew A B 命令表示执行任务A和B,支持驼峰简写。
我们创建一个简单的Andoid项目在app下的build.gradle中来试着写一个简单的任务
我们可以点击绿色三角执行该任务,也可以使用命令行执行,命令行执行如下:任选其一,即可在控制台看到输出的结果
D:\TestCode\GeadleLearning>gradlew pH
D:\TestCode\GeadleLearning>gradlew printHello
关于task的其它特性
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.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 "构建结束时调用" } })
在一个拥有复杂功能的Android项目中,往往少不了许多的第三方SDK与模块化管理,而Gradle在这些复杂的SDK依赖关系、模块间的依赖关系中起着至关重要的作用,下面就来介绍下Geadle如何管理各种各样的依赖关系吧。
在整个工程下的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"
}
}
}
在 dependencies 代码块内,我们可以选择不同的依赖项配置来声明库的依赖项,每种不同的依赖项都具有不同的特点,详情可以参考Google对依赖项配置的文档
这里截取一部分
当我们使用Gradle来管理项目依赖的时候,Gradle再编译的时候会对我们的依赖进行优化,例如我们在app模块的依赖中依赖重复的库,在编译之后查看依赖情况:
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:dependencies --configuration releaseRuntimeClassPath查看编译后的依赖情况,常见三种情况解释如图:
我们在从输出信息当中寻找到我们重复依赖的androidx.appcompat:appcompat,看Gradle是如何处理的,结果如下图:我们可以看到不管是低版本还是取最新版本都被替换成最新版本,并且这两条依赖都是被忽略的,因为最新版本的该库在前面已经被添加了。
依赖冲突
依赖冲突的本质就是存在两个同样的类,这两个类具有相同的包名和类名,这在java中是不被允许的,因此就会产生依赖冲突。
例如我们引入了一个依赖包,他的结构如下,如果在另一个依赖中包含如下红框中的一些类的话,就会产生依赖冲突,那么我们如何解决呢?
假设我们需要排除红框中的依赖包,我们可以选择一下方式来解决:
implementation('androidx.room:room-runtime:2.5.0') {
exclude group: 'androidx.room', module: 'room-common'
}
再次使用gradlew :app:dependencies --configuration releaseRuntimeClassPath进行编译:已经没有之前的子Module依赖了,因此可以通过上述方式解决依赖冲突。
还可以将整个依赖下面的某个Group干掉,可以发现以androidx.sqlite开头的Group全部消失了
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'
}
}
依赖传递就是用来控制某个模块导入的包是否可以被其它模块直接使用,主要涉及implementation 与 api
最简单的解释如下:
有A、B、C、D四个模块
A implementation B,B implementation C 则A不能使用C
A implementation B,B api C 则A可以使用C
A implementation B,B implementation C ,C api D 则B可以使用D,A不能使用D
A implementation B,B api C ,C api D 则A可以使用D
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。