
无论是否意识到Gradle的存在,每个Android程序员都会直接或间接地处理Gradle. 每当通过Android Studio创建新项目时,AS都会自动创建一个通用目录结构,然后您可以进行开发,在应用程序的build.gradle中添加一些依赖项,单击右上角的立即同步,编写代码,单击绿色小箭头运行代码,一切都很好,只是偶尔“立即同步”将失败并变为“重试”. 如果几次重试后问题仍未解决,请打开浏览器,粘贴相应的错误,找到解决方案,复制并粘贴解决方案gradle 不是内部或外部,单击“重试”,问题就解决了,寿命仍然如此.
如果您想了解问题发生的原因以及解决问题的原因,那么您需要摆脱AS的常见按钮,并探究其背后的秘密-自动构建工具Gradle.
本文将介绍:
为什么需要自动构建工具?默认创建的Android项目具有任何依赖项管理打包过程
通过阅读本文,您可以大致了解Gradle的工作原理,可以有针对性地搜索相关内容,并更快地解决常见的编译错误
以下命令仅是有助于说明问题的示例. 具体用法请参考相关命令手册用法
我们知道APK包实际上是一个包含代码和资源的zip包. 然后我们可以编写一个名为assemble.sh的Shell脚本,任何人都可以通过执行以下脚本来获得apk包,完美:
# 将 .java 文件转换为 .class 文件,执行命令
javac xxx.java
# Android 还会将 .class 文件转换为 .dex 文件
dx xxx.class
打包成 apk
zip xxx.apk [需要打包的代码和资源]
在Android中,代码通过R.java文件引用资源,因此您需要继续添加命令,并要求在javac命令之前执行此命令. 在实际开发中,我们不可能独自实现所有功能,并且我们可能依赖于出色的开源库. 修改后的伪代码如下:
# 生成 R.java
aapt [资源文件]
# 将 .java 文件转换为 .class 文件,执行命令
javac xxx.java R.java -classpath xxx.jar
# Android 还会将 .class 文件转换为 .dex 文件
dx xxx.class R.class xxx.jar
# 打包成 apk
zip xxx.apk [需要打包的代码和资源]
一切似乎都在掌控之中,真的吗?让我们看看Android APK的实际打包过程是什么样的:
考虑实现如此复杂过程的shell脚本是否有点大?不用担心,实施后会遇到以下问题:
这时,我们需要一个简化上述过程的工具. 通过一些约定,例如将代码和资源放在指定目录中,然后补充构建脚本,您可以快速获得最终的构建产品. 这是自动构建工具,Gradle就是其中之一.
与现在的简单示例相比,每个项目都称为Gradle中的Project,而每个需要执行的任务(例如生成R文件和编译Java文件)都称为Gradle中的Task. TaskA.dependsOn(TaskB)可以实现先执行TaskB,然后再执行TaskA的效果. 同时,Gradle还提供了doFirst和doLast,以允许在每个Task之前和之后执行一些代码.
在这一点上,我们知道为什么需要自动化的构建工具:
无论何时通过Android Studio创建新项目,AS都会自动创建目录结构,如上图所示. 图片简要介绍了每个目录的作用,然后详细介绍了每个目录或文件的含义:
.gradle和.idea存储当前项目的Gradle和AS缓存.
最常见的应用程序之一是,单击“同步”后,AS将在每个项目下生成.iml文件. 它们与.gradle和.idea一起,为我们提供了常见的功能,例如代码提示. 因此,如果您的代码为红色,并且确认依赖性没有问题,则可以尝试以下步骤清除AS缓存:
删除.idea删除.gradle文件并从命令行执行. /gradlewclean选择“文件”->“使缓存无效/ restartSync”
当我们第一次配置Android环境时,我们需要安装Java和AS,但不需要安装Gradle,这是gradle / wrapper的功劳.
在执行gradlew脚本时,可以确保每个项目都使用期望的Gradle版本,而其中的奥秘在于gradlew的代码中
exec"$JAVACMD""${JVM\_OPTS\[@\]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain"$@"
gradlew不会直接启动Gradle,而是启动gradle-wrapper.jar,它将判断是否没有Gradle环境,从gradle-wrapper.properties中的distributionUrl下载相应的环境,然后启动Gradle.
由于Gradle在启动命令行时允许自定义其他参数,因此百度应用程序自定义gradle-wrapper.jar以为具有不同内存大小的计算机实现不同的gradle操作,并通过配置文件Memory调试/发布程序包,从而改善每个人的编译速度.
setting.gradle中最重要的是它提供的include方法. 通过这种方法,您可以指定哪些项目需要参与编译. 每个参与Gradle编译的项目都会为其创建一个Project对象
首先是buildscript代码块:
gradle默认情况下从上到下执行,无论buildscript代码块在哪里,都将首先执行
接下来是存储库和依赖项:
存储库指示依赖项声明要查找的依赖项的存储库. Google,jcenter和mavenCentral都是第三方Maven存储库. 同时,您还可以通过maven方法添加自己的Maven存储库. 应当注意,不应假定将从特定仓库中提取组件. 如果Gradle请求仓库超时,它将自动请求其他仓库.
依赖关系: 表示Gradle执行所需的依赖关系. 例如,如果您需要Android Gradle插件为我们打包apk包,则需要添加
classpath 'com.android.tools.build:gradle:3.4.0'
最后,所有项目和存储库:
所有项目中的配置将对所有项目均有效,并且其中的存储库指示项目声明要依赖的存储库
首先,您可以看到apply插件: “ com.android.application”. 应用此插件后,它将为我们创建一系列任务,例如assembleDebug,assembleRelease,执行这些任务,您将获得最终的APK.
android代码块是插件提供的API,可让我们修改Task的行为.
依赖项代码块的内容确定当前项目依赖于哪些组件,并且不同的依赖项声明将具有不同的结果. 我们将在下一部分中分析具体内容.
在Android Gradle Plugin 3.0时代,Google使用实现和api选项代替了过去的编译选项. 现在界面已经更改,Google只是简单地重命名了其他配置项,以使每个人都更容易理解其配置的含义. 应当注意,该接口的旧版本不会立即删除,而是会在下一个主要版本中删除. 以下是每个配置项的官方中文说明:
例如:
假设A取决于B,B取决于C.
如果B使用对C的实现依赖性,则A无法调用C的代码

如果B对C使用api依赖关系,则A可以调用C的代码
如果B对C使用compileOnly依赖关系,则A无法调用C的代码,并且C的代码也不会打包到APK中
如果B使用runtimeOnlyOnlyOnly仅依赖于C,则A和B无法调用C的代码,但是C的代码将打包到APK中
实际上,每个组件都有其自己的compileClasspath和runtimeClasspath
当组件参与编译时,Gradle会将其放入compileClasspath
当组件参与包装时,Gradle会将其放入runtimeClasspath
实际上,不同的依赖项配置项将声明的依赖项放入不同组件的不同类路径中,并返回到上面的示例
为了实现,实际上是将C放入B的compileClasspath和runtimeClasspath中,并放入A的runtimeClasspath中,以便实现A. 如果调用C的代码,则javac在A的编译阶段会报告一个错误,但最终会报告C将被打包到APK中.
同一原理适用于api,compileOnly和runtimeOnly
当您要依赖源代码项目时,只需这样写
implementation project(':demo:mylibrary')
我们可以清楚地知道,库中的依赖项将被正确打包到APK中
当我们依赖二进制文件时,我们需要这样写
implementation 'androidx.appcompat:appcompat:1.0.2'
执行相关命令时(仅输出发行包的runtimeClasspath)
`./gradlew :app:dependencies --configuration releaseRuntimeClasspath > dependencies.txt`
在输出依赖关系图时,您将看到它不仅依赖于appcompat组件(仅显示某些依赖项),而且还包含该组件自己的依赖项和依赖项依赖项,直到该组件本身具有没有依赖关系. 这种功能称为依赖项传递.
releaseRuntimeClasspath - Resolved configuration for runtime for variant: release
\--- androidx.appcompat:appcompat:1.0.2
+--- androidx.annotation:annotation:1.0.0
+--- androidx.core:core:1.0.1
| +--- androidx.annotation:annotation:1.0.0
| +--- androidx.collection:collection:1.0.0
| | \--- androidx.annotation:annotation:1.0.0
| +--- androidx.lifecycle:lifecycle-runtime:2.0.0
| | +--- androidx.lifecycle:lifecycle-common:2.0.0
| | | \--- androidx.annotation:annotation:1.0.0
| | +--- androidx.arch.core:core-common:2.0.0
| | | \--- androidx.annotation:annotation:1.0.0
| | \--- androidx.annotation:annotation:1.0.0
| \--- androidx.versionedparcelable:versionedparcelable:1.0.0
| +--- androidx.annotation:annotation:1.0.0
| \--- androidx.collection:collection:1.0.0 (*)
+--- androidx.collection:collection:1.0.0 (*)
+--- androidx.cursoradapter:cursoradapter:1.0.0
那么Gradle如何确定这些依赖关系?使用Maven规范上载组件时,不仅上载组件的二进制文件,还上载pom.xml文件,并且相关性信息也位于该文件中.
由于您可能需要翻墙查看公共Maven服务器,因此下面向您显示了由百度应用程序构建的服务器的背景,以帮助您了解上传的二进制文件如何存储在服务器上
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/ruanjian/article-201115-1.html
对于没有加入公约的美国
前9个月的CPI是1
质检局自己去买来检测的是假货