【Gradle】基本使用及注意事项

一、日常记录

1.父子模块依赖

1.平级依赖

    settings.gradle添加:
        includeFlat  'A'
    build.gradle添加:
        compile project(':A')

2.聚合工程

    settings.gradle添加:
        include 'C1','C2'

2.生命周期钩子

https://blog.csdn.net/wolfcode_cn/article/details/83658015

3.查看项目依赖树

1、用gradle命令查看依赖关系:

gradle dependencies	
./gradlew dependencies	

2、用idea查看依赖关系:
在这里插入图片描述

4.生成指定版本gradlew

gradle wrapper --gradle-version [版本号]
//例:gradle wrapper --gradle-version 6.9.1

5.Java使用Gradle依赖配置compile,implementation和api的区别

Gradle3.4新增了Java-library插件,java-library插件使用了新的依赖配置implementation和api。旧的依赖配置compile被废弃。

Gradle3.4之前的版本:
java插件

apply plugin: 'java'

添加依赖

dependencies {
compile 'commons-httpclient:commons-httpclient:3.1'
compile 'org.apache.commons:commons-lang3:3.5'
}

Gradle 3.4+
使用java-library插件替换java插件

apply plugin: 'java-library'

新的依赖配置:implementation和api

dependencies {
api 'commons-httpclient:commons-httpclient:3.1'
implementation 'org.apache.commons:commons-lang3:3.5'
}

api和implementation两种依赖的不同点在于:它们声明的依赖其他模块是否能使用。

  • api:当其他模块依赖于此模块时,此模块使用api声明的依赖包是可以被其他模块使用
  • implementation:当其他模块依赖此模块时,此模块使用implementation声明的依赖包只限于模块内部使用,不允许其他模块使用。

二、Gradle命令

1.常用命令

gradle命令一般是 ./gradlew +参数, gradlew代表 gradle wrapper,意思是gradle的一层包装,大家可以理解为在这个项目本地就封装了gradle,即gradle wrapper, 在gradle/wrapper/gralde-wrapper.properties文件中声明了它指向的目录和版本。只要下载成功即可用grdlew wrapper的命令代替全局的gradle命令。

./gradlew -v 版本号
./gradlew clean 清除app目录下的build文件夹
./gradlew build 检查依赖并编译打包
./gradlew tasks 列出所有task

这里注意的是 ./gradlew build 命令把debug、release环境的包都打出来,如果正式发布只需要打Release的包,该怎么办呢,下面介绍一个很有用的命令 assemble, 如:

./gradlew assembleDebug 编译并打Debug包
./gradlew assembleRelease 编译并打Release的包

除此之外,assemble还可以和productFlavors结合使用:

./gradlew installRelease Release模式打包并安装
./gradlew uninstallRelease 卸载Release模式包

2.加入自定义参数

比如我们想根据不同的参数来进行不用的编译配置,可以在./gradlew中加入自定义参数。

./gradlew assembleDebug -Pcustom=true
 
可以在build.gradle中使用下面代码来判断:
if (project.hasProperty('custom')){
}

三、Gradle配置

Gradle构建脚本 build.gradle
Gradle属性文件 gradle.properties
Gradle设置文件 settings.gradle

1.build.gradle

先看整个项目的gradle配置文件:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.3.0'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
allprojects {
    repositories {
        jcenter()
    }
}

内容主要包含了两个方面:一个是声明仓库的源,这里可以看到是指明的jcenter(), 之前版本则是mavenCentral(), jcenter可以理解成是一个新的中央远程仓库,兼容maven中心仓库,而且性能更优。
另一个是声明了android gradle plugin的版本,android studio 1.0正式版必须要求支持gradle plugin 1.0的版本。
上面的 buildscript 和 allprojects 其实是 Project 类的一个 Script blocks,Gradle 中每个 build.gradle 会转换成一个 Project 对象。

(1).buildscript
buildscript {
    repositories {
        maven { url 'http://*********' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.3.1'
    }
}
  • buildscript{}设置脚本的运行环境。
  • repositories{}支持java依赖库管理,用于项目依赖。
  • dependencies{}依赖包的定义。支持maven/ivy,远程,本地库,也支持单文件。如果前面定义了repositories{}maven 库,则使用maven的依赖库,使用时只需要按照用类似于com.android.tools.build:gradle:0.4,gradle 就会自动的往远程库下载相应的依赖。
(2).apply
apply plugin: 'com.android.library'

apply from: "config.gradle"
apply from: '../buildscript.gradle', to:buildscript  // 导入到 buildscript 块
  • apply plugin:声明引用插件的类型。
  • apply from:表示引用其他的配置文件
(3).android

(4).repositories
repositories {
    flatDir {
        //本地jar依赖包路径
        dirs '../../../../main/libs'
    }
}
(5).dependencies
dependencies {
        // 单个引入依赖
        compile files('libs/android-support-v4.jar')
        //在flatDir.dirs下面找依赖的aar
        compile (name:'ui', ext:'aar')
        // 编译extras目录下的ShimmerAndroid模块
        // 使用transitive属性设置为false来排除所有的传递依赖,默认为true
        compile project(':extras:ShimmerAndroid'){
            transitive = false
        }
        // 编译CommonSDK模块,但是去掉此模块中对com.android.support的依赖,防止重复依赖报错
        compile (project(':CommonSDK')) { exclude group: "com.android.support" }
        provided fileTree(dir: 'src/android5/libs', include: ['*.jar'])
        provided 'com.android.support:support-v4:21.0.3'
        provided project(':main-host')
        //通用使用exclude排除support-compat模块的依赖
        compile ('com.jakewharton:butterknife:8.5.1'){
            exclude module: 'support-compat'
        }
        // gradle 3.0以后版本支持的写法
        implementation 'com.android.support.constraint:constraint-layout:1.0.2'
        api 'com.android.support:design:26.1.0'
        // 指定使用aar格式的依赖包,但是这样会关闭依赖传递
        implementation 'com.android.support:appcompat-v7:22.1.1@aar
}
  • compile 和 provided
    • compile表示编译时提供并打包进apk。
    • provided表示只在编译时提供,不打包进apk。
  • implementation 和 api
    • 这两个是 Gradle 3.0 以后的依赖方法,implementation 在编译期会将依赖隐藏在内部而不对外公开,就是说使用 implementation 的依赖不会传递。只有在运行时其他模块才能获取依赖。比如:一个项目中app模块依赖A模块,A模块使用 implementation 来依赖 fastjson ,那么app里面如果不添加依赖的话就不能直接引用fastjson,会编译不通过。这样做的好处是1.加快编译速度,2. 隐藏对外不必要的接口。
    • api 和以前的 compile 是一样的。

gradle 3.0以后使用 compileOnly 来代替 provided,使用 runtimeOnly 来代替 apk

  • exclude 防止重复依赖,后面会重点介绍
  • transitive 排除所有的传递依赖,后面会重点介绍
  • include
(6).本地依赖

本地依赖指的是我们把jar包或者aar包放到本地依赖的方法,这样就不用发布到远程仓库。

默认情况下,新建的Android工程有一个libs目录,并且被添加为依赖目录。

dependencies {
    compile fileTree('libs')
}

还可以添加过滤器,只添加 Jar 依赖包:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

还可以单个添加依赖:

dependencies {
    compile files('libs/xxx.jar') // aar 也可以
}

//或者(但是这样会关闭依赖传递)
dependencies {
    compile(name:'libraryname', ext:'aar')
}

我们还可以指定目录地址作为放置依赖包的目录:

repositories {
    flatDir {
        dirs 'jars'
    }
}

//指定多个:
repositories {
    flatDir {
        dirs 'jars';dirs 'aars'
    }
}
(7).本地仓库

除了上面的本地直接添加依赖包的方法,我们还可以设置本地仓库:

repositories {
    maven {
        url "../repo"
    }
}
(8).几点说明
  • 看到上面的两个一模一样的repositories和dependencies了吗?他们的作用是不一样的,在buildscript里面的那个是插件初始化环境用的,用于设定插件的下载仓库,而外面的这个是设定工程依赖的一些模块和远程library的下载仓库的。

  • @aar 的使用:aar(Android Archive)和jar(Java Archive File)之间的区别:aar 可以包含源代码和资源(包含 AndroidManifest.xml 布局文件等资源文件),但是 jar 只能包含源代码。当您在项目的build.gradle 中包含一个带有后缀 @arr 的库时,该库将下载 aar 后缀的库文件。如果没有,默认情况下将下载 jar 文件。当然,您也可以添加后缀@jar使下载 jar 库文件。比如:implementation ‘com.android.support:appcompat-v7:22.1.1@aar’

2.settings.gradle

这个文件是全局的项目配置文件,里面主要声明一些需要加入gradle的module。

一般在setting.gradle中主要是调用include方法,导入工程下的各个子模块。

那我们在setting.gradle里面还能写什么呢?因为setting.gradle对应的是gradle中的Settings对象,那查下Settings的文档(https://docs.gradle.org/current/dsl/org.gradle.api.initialization.Settings.html),看下它都有哪些方法,哪些属性,就知道在setting.gradle能写什么了;

nclude ':AndroidDemo'
include ':CommonSDK'
project(':CommonSDK').projectDir = new File(settingsDir, '../../CommonSDK/')

include调用后,生成了一个名为:CommonSDK的Project对象,project(‘:CommonSDK’)取出这个对象,设置Project的 projectDir属性。projectDir哪里来的?请看Project类的文档。

3.gradle.properties

可以在 gradle.properties 文件中配置一些变量,这些变量在这个工程下的所有module的build.gradle文件里都可以使用。这样就可以把一些共用的变量放到这里,这样后面修改的时候就可以只修改这个变量,不用各个模块都要修改了。

比如我们在 gradle.properties SDK 版本以及应用的版本号:

MIN_SDK_VERSION=21
TARGET_SDK_VERSION=22
VERSION_CODE=200100
VERSION_NAME=2.1.0
debug=true
RX_ANDROID_VERSION=1.2.0

那么在 build.gradle 中可以通过project进行获取或者 “${RX_ANDROID_VERSION}” 引用:

    defaultConfig {
        applicationId "com.example.heqiang.testsomething"
        minSdkVersion project.MIN_SDK_VERSION as int
        targetSdkVersion project.TARGET_SDK_VERSION as int
        versionCode project.VERSION_CODE as int
        versionName project.VERSION_NAME
        // 还可以这样获取
        if('true' == project.properties['debug']){
        }
        /*
        * as int 关键字是用来进行类型转换的,因为从配置里面读取出来的默认是字符串
        *还可以使用 versionCode Integer.parseInt(project.VERSION_CODE)
        * */
    }
// 还可以这样用
dependencies {
    compile "io.reactivex:rxandroid:${RX_ANDROID_VERSION}"
    compile "io.reactivex:rxjava:${RX_JAVA_VERSION}"
}

或者在 gradle.properties 中添加:

systemProp.versionName=1.0.0
systemProp.versionCode=100

可以通过 System.properties进行引用:

def code = System.properties['versionCode']
def name = System.properties['versionName']

4.调试

我们在进行一些配置的时候可能需要知道一些变量的值,这时候可以在 build.gradle 中添加打印进行调试,比如:

defaultConfig {
    applicationId "com.example.hq.testsomething"
    minSdkVersion project.MIN_SDK_VERSION as int
    targetSdkVersion project.TARGET_SDK_VERSION as int
    versionCode project.VERSION_CODE as int
    versionName project.VERSION_NAME
    println('** build versionName=' + versionName)
}

在 Gradle Console 中就可以看到打印

** build versionName=2.1.0

如果找不到 Gradle Console ,可以 View ->Tool Windows -> Gradle, 任意选择一个Task,双击执行即可。

或者使用命令行编译。

四、依赖库管理

1.本地依赖

dependencies {
	    //单文件依赖
        compile files('libs/android-support-v4.jar')
	    //某个文件夹下面全部依赖
        compile fileTree(dir: 'src/android6/libs', include: ['*.jar'])
        compile (name:'ui', ext:'aar')
	    compile (project(':CommonSDK')) { exclude group: "com.android.support" }
        provided fileTree(dir: 'src/android5/libs', include: ['*.jar'])
        provided 'com.android.support:support-v4:21.0.3'
        provided project(':main-host')
}

2.远程依赖

repositories { 
 //从中央库里面获取依赖
 mavenCentral() 
 //或者使用指定的本地maven 库
 maven{ 
  url "file://F:/githubrepo/releases" 
 }
 //或者使用指定的远程maven库
 maven{ 
  url "https://github.com/youxiachai/youxiachai-mvn-repo/raw/master/releases" 
 } 
} 
dependencies { 
 //应用格式: packageName:artifactId:version 
 compile 'com.google.android:support-v4:r13' 
}

3.Gradle依赖的统一管理

我们可以在项目的根目录创建一个gradle配置文件config.gradle,内容如下:

ext{
    android=[
            compileSdkVersion: 22,
            buildToolsVersion: "23.0.1",
            minSdkVersion: 21,
            targetSdkVersion: 22,
            versionCode: 1,
            versionName: "1.0"
    ]
    dependencies=[
            compile:'com.android.support:support-v4:21.0.3',
            compile: (project(':CommonSDK')) { exclude group: "com.android.support" },
            provided: fileTree(dir: 'src/android5/libs', include: ['*.jar']),
            provided: project(':main-host')
    ]
}

targetSdkVersion的版本还有依赖库的版本升级都在这里进行统一管理,所有的module以及主项目都从这里同意读取就可以了。

在build.gradle文件中加入:

apply from:"config.gradle"

意思是所有的子项目或者所有的modules都可以从这个配置文件中读取内容。

android节点读取ext中android对应项,dependencies读取dependencies对应项,如果配置有变化就可以只在config.gradle中修改,是不是很方便进行配置的管理呢?

4.检查依赖报告

运行命令./gradlew :dependencies (projectname为settings.gradle里面配置的各个project,如果没有配置,直接运行./gradlew dependencies),会把该模块所有配置的依赖树会打印出来,依赖树显示了你 build 脚本声明的顶级依赖和它们的传递依赖。

为了减少输出内容我们只对 compile configuration感兴趣,那么可以运行下面的命令:

./gradlew <projectname>:dependencies --configuration compile

在这里插入图片描述
仔细观察你会发现有些传递依赖标注了(*)星号,表示这个依赖被忽略了,这是因为其他顶级依赖中也依赖了这个传递的依赖,Gradle会自动分析下载最合适的依赖,一般是比较新的版本。(->)箭头表示被强转变依赖于箭头后面的版本

如果在 Gradle 3.0 以后可以运行:

./gradlew <projectname>:dependencies --configuration releaseRuntimeClasspath

5排除传递依赖

Gradle允许你完全控制传递依赖,你可以选择排除全部的传递依赖也可以排除指定的依赖。

  • exclude:可以设置不编译指定的模块,排除指定模块的依赖。后的参数有group和module,可以分别单独使用,会排除所有匹配项。
// 编译CommonSDK模块,但是去掉此模块中对com.android.support的依赖,防止重复依赖报错
compile (project(':CommonSDK')) { exclude group: "com.android.support" }
compile ('com.jakewharton:butterknife:8.5.1'){
    exclude module: 'support-compat'
    exclude group: 'com.android.**.***', module: '***-***'
}
  • transitive:前面已经介绍过,用于自动处理子依赖项,默认为true,gradle自动添加子依赖项。设置为false排除所有的传递依赖,可以用来解决一些依赖冲突的问题,比如一些 Error:java.io.IOException: Duplicate zip entry 报错。
/ 使用transitive属性设置为false来排除所有的传递依赖
compile project(':extras:ShimmerAndroid'){
    transitive = false
}
  • force:强制设置某个模块的版本。
configurations.all{
    resolutionStrategy{
        force'org.hamcrest:hamcrest-core:1.3'
    }
}

//或
compile ('com.jakewharton:butterknife:8.5.1'){
    // 冲突时优先使用该版本
    force = true
}

6.动态版本声明

如果你想使用一个依赖的最新版本,你可以使用latest.integration,比如声明 Cargo Ant tasks的最新版本,你可以这样写org.codehaus .cargo:cargo-ant:latest-integration,你也可以用一个+号来动态的声明:

dependencies {
	//依赖最新的1.x版本
	compile "org.codehaus.cargo:cargo-ant:1.+"
}

然后在依赖树里面可以清晰的看到选择了哪个版本:

\--- org.codehaus.cargo:cargo-ant:1.+ -> 1.3.1

五、gradle部署

1.linuxgradle包位置

在这里插入图片描述

Gradle 官方文档:Gradle User Manual:https://docs.gradle.org/current/userguide/userguide.html

Gradle 官方文档:Gradle Tutorials and Guides
https://gradle.org/guides/

Gradle User Guide 中文版
https://dongchuan.gitbooks.io/gradle-user-guide-/

http://www.heqiangfly.com/categories/Gradle/

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值