Gradle For Androider

Gradle思想

在软件开发过程中,编码,编译,打包,测试,这几个过程必不可少,这些过程中有些步骤的重复性非常高,在没有构建工具之前,开发人员需要自己手动的编译,手动的打包,这些操作都是可以通过重复的有序的步骤来完成的,Gradle就可以帮助我们自动的编译,打包,从而提高开发的效率和质量;

闭包

Gradle是基于Groovy语言工作的,Groovy语言和java的相似度非常高,这里介绍一个java没有的概念,闭包是一个类:用于描述一个可以接受参数和返回值的代码块;

Closure closure = {
    it -> println("闭包")
}

it 是隐式参数,用于描述当前闭包,和java的this差不多

task

task是gradle中一个很重要的概念,代表一个原子性操作,安卓项目的编译,打包的细节,都是通过一个个task来完成的:

task hello() {
    print("say hello")
}

task clean(type: Delete) {
    delete rootProject.buildDir
    doFirst {
        println("clean start")
    }
    doLast {
        println("clean end")
    }
}

注意doFirst和doLast函数,在下面会详细介绍

gradle 工作流程

在了解Gradle的构建流程前,需要知道两个概念,Project,Task,每一个待编译的工程都叫做Project,每一个Project都包含了多个Task,比如Android APK的编译,可能包括Java源代码编译,资源编译,打包,签名;这些编译任务都是通过一个一个的Task完成的;

  1. Initialization:初始化阶段,Gradle 将会确定哪些项目将参与构建,并为每个项目创建一个 Project 对象实例。对于 Android 项目来说即为执行 setting.gradle 文件;

一般setting.gradle都是这样的:通过include函数将所有的Project包含进来

include ':app', ':a', ':b'
  1. Configuration:配置阶段,会解读每一个build.gradle文件,分析里面的task,然后将这些task形成一个有向图,表示task的依赖关系
task testBoth {
	println '我会在 Configuration 和 Execution 阶段都会执行'
    doFirst {
      println '我仅会在 testBoth 的 Execution 阶段执行'
    }
    doLast {
      println '我仅会在 testBoth 的 Execution 阶段执行'
    }
}

写在Task闭包的任务会在Configuration阶段运行,而doFirst,doLast会在Execution阶段运行;
切记大部分的内容是写在 doLast{} 或 doFirst{} 闭包中,因为写在如果写在 task 闭包中的话,会在 Configuration 阶段也被执行。

  1. Execution:task 的执行阶段。首先执行 doFirst {} 闭包中的内容,最后执行 doLast {} 闭包中的内容。

image
我们可以hook默认的构建过程,加入一些自定义的操作;

Gradle Wrapper

Gradle Wrapper是一个脚本,可以帮助我们自动安装和运行Gradle,只需要指定Gradle的版本就好了
Android Studio中的Gradle Wrapper
在Android Studio项目中的这些目录,都是和Gradle Wrapper相关的文件:

  • gradle-wrapper.jar:gradle运行的逻辑代码
  • gradle-wrapper.properties:用来配置gradle的属性文件,主要可以配置以下内容:
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
  1. distribution相关的两个是配置gradle解压后存放的位置
  2. zip相关的是存放gradle压缩包存放的位置
  3. distributionUrl用来Gradle官网以及发版压缩包的下载地址
  • gradlew:Linux平台执行gradle命令的脚本文件
  • gradlew.bat:Windows平台执行gradle命令的脚本文件

Android插件

构建文件的目录:
  • 项目build.gradle:配置项目的整体属性,gradle插件版本,代码仓库
  • 模块build.gradle:当前模块的编译设置,下面会具体介绍两个块,Android块和dependency块
  • setting.gradle:当前项目引入的模块都需要在这里声明
Android 块
// androdi块
android {
    compileSdkVersion 30  // 编译该模块的SDK版本
    buildToolsVersion "30.0.2"  // Android构建工具版本

    // 默认配置块
    defaultConfig { 
        applicationId "com.example.myapplication" // APP包名
        minSdkVersion 23     // 支持的最低SDK版本
        targetSdkVersion 30  // 基于开发的SDK版本
        versionCode 1        // App内部的版本号
        versionName "1.0"    // App版本名称,发布的版本号

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"  // 单元测试使用的Runner
    }

    // 用于配置构建不同的apk,debug,release
    buildTypes {
        // release apk
        release {
            minifyEnabled false // 是否混淆
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' // ProGuard混淆使用的混淆配置文件
        }
        // debug apk
        debug{
            applicationIdSuffix ".debug" // 添加 applicationId 的后缀
            debuggable true // 是否支持断点调试
        }
    }

    signingConfigs{
        storeFile file("C:/...") // 签名证书文件
        stroePassword "" // 签名的密码
        storeType "" // 签名证书的类型
        keyAlias "" // 签名证书密钥的别名
        keyPassword "" // 签名证书中密钥的密码
    }
}
dependency块

用于配置该module构建过程中所有依赖的库,可以使用两个函数来依赖:

  • implementation:可以让模块在编译时隐藏自己使用的依赖,但是在运行时对所有模块是可见的
  • api:无法在编译时隐藏使用的依赖,如果一个模块发生变化,整条依赖链上的模块都需要重新编译,而使用implementation只会重新编译这个模块
全局配置

如果有多个模块,可以使用一个全局配置将所有模块进行统一管理

  1. 在项目build.gradle 中使用ext块:
ext{
    compileSdkVersion = 28
    minSdkVersion = 15
    targetSdkVersion = 27
}

// 在模块build.gradle中使用
    targetSdkVersion rootProject.ext.targetSdkVersion
Gradle 依赖管理
  • transitive:禁止依赖传递
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'{
        transitive false
    }
  • force:强制这个库使用统一版本
    在模块build.gradle中添加如下代码
configurations.all {
    resolutionStrategy{
        force 'androidx.appcompat:appcompat:1.1.0'
    }
}
  • exclude:排除库依赖传递中设计的库
    compile ('com.xxx.wireless.xx-update:1.0.17'){
        exclude(group: 'com.xxx.wireless.xx', module: 'xx-tools')
    }

组件化搭建:

1.版本统一管理
  1. 新建一个gradle文件,生命一些变量,用于全局配置
ext {
    isRelease = false
    configMap = [
            compileSdkVersion : 28,
            applicationId : "com.leap.latte",
            minSdkVersion: 23,
            targetSdkVersion:28,
            versionCode : 1,
            versionName : "1.0"
    ]
}
  1. 在根build.gradle文件中 引入 apply from: ‘config.gradle’ 才能使用
apply from: 'config.gradle'
  1. 使用配置统一管理,在各个build.gradle中都可以使用
    compileSdkVersion configMap.compileSdkVersion
2. 组件的Release和Debug自动切换
if (isRelease){
    apply plugin: 'com.android.library'     // 不可以独立运行 不需要applicationId,依赖app壳
}else {
    apply plugin: 'com.android.application'   // 可以独立运行 需要 applicationId  ,不依赖app壳
}
3. Gradle变量在Java中使用
android {
    compileSdkVersion configMap.compileSdkVersion
    defaultConfig {
        applicationId "com.leap.latte"
        minSdkVersion 23
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
		
		 // gradle 的变量放到java用
        buildConfigField("boolean","isRelease",String.valueOf(rootProject.isRelease)) 
    }
}

sync后会生成Java类BuildConfig

/**
 * Automatically generated file. DO NOT MODIFY
 */
package com.leap.latte;

public final class BuildConfig {
  public static final boolean DEBUG = Boolean.parseBoolean("true");
  public static final String APPLICATION_ID = "com.leap.latte";
  public static final String BUILD_TYPE = "debug";
  public static final String FLAVOR = "";
  public static final int VERSION_CODE = 1;
  public static final String VERSION_NAME = "1.0";

  // Fields from default config.
  public static final boolean isRelease = false;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值