Gradle

654 阅读4分钟

零散的点

1. gradle是构建工具,不是语言.使用了Groovy这个语言,但gradle本身不是语言.

2. 闭包:一对大括号,相当于可以被传递的代码块/方法. Groovy可用直接传递方法本身,Java不可以.

buildscript {
    repositories {
        ***
    }
    dependencies {
        ***
    }
}

相当于

buildscript ({
    repositories {
        ***
    }
    dependencies {
        ***
    }
})

{}及其内部的代码构成1个闭包,闭包被当做参数传入buildscript方法.闭包内部的代码会在后面某个时间被执行.
同理,

repositories {
    google()
    jcenter()
}

相当于

repositories ({
    google()
    jcenter()
})
闭包/方法本身被当做参数传入 repositories 方法.

3. buildscript解释

***\Jet2020\build.gradle
buildscript {
  //R:用于配置依赖/D的仓库地址
  repositories {
    google()
    jcenter()
  }
  //D:依赖
  //依赖是给 gradle plugin/P 用的
  dependencies {
    //classpath指定了要用哪些plugin,plugin从什么位置下载,由R决定
    classpath 'com.android.tools.build:gradle:4.0.0'
  }
}
allprojects {
  //R2
  //上面的R是包在buildscript里面,用于整体上对gradle plugin做配置.比如app模块引用的 apply plugin: 'com.android.application'.
  //而R2是用于具体模块的依赖,比如A moudle依赖中引入了Retrofit,OKHttp等开源库,其仓库地址就通过R2配置.
  repositories {
    google()
    jcenter()
  }
}

***\Jet2020\app\build.gradle
//P
//plugin:application这个plugin
//plugin获取的位置,就是通过D中的 classpath 配置的
apply plugin: 'com.android.application'

4. classpath

dependencies {
    classpath 'com.android.tools.build:gradle:4.0.0'
}

相当于

dependencies {
    add('classpath', 'com.android.tools.build:gradle:4.0.0')
}

5. allprojects

allprojects {
    repositories {
        google()
        jcenter()
    }
}

相当于

//这种写法很像Java里面的addListener写法.
allprojects(new Action<Project>() {
    @Override
    void execute(Project project) {
        repositories {
            google()
            jcenter()
        }
    }
})

6. buildTypes

1.常见用法,区分不同的版本进行不同展示: 在buildTypes中新建1个build类型 -> internal

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
    debug {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
    //新建一个构建类型
    internal {
        initWith debug
    }
}

在src中新建 debug, internal 2个文件夹,内部结构都一致,包含同名工具类BuildTypeUtils debug和internal下 BuildTypeUtils 的逻辑不同.

src/internal/java/com/huanhailiuxin/gradle20201015/BuildTypeUtils.java
public final class BuildTypeUtils {
    public static void drawBadge(Activity activity) {
        ViewGroup viewGroup = (ViewGroup) activity.getWindow().getDecorView();
        TextView textView = new TextView(activity);
        textView.setGravity(Gravity.CENTER);
        textView.setBackgroundColor(Color.BLUE);
        textView.setText("Internal");
        viewGroup.addView(textView, 200, 200);
    }
}

src/debug/java/com/huanhailiuxin/gradle20201015/BuildTypeUtils.java
public final class BuildTypeUtils {
    public static void drawBadge(Activity activity) {
        ViewGroup viewGroup = (ViewGroup) activity.getWindow().getDecorView();
        TextView textView = new TextView(activity);
        textView.setGravity(Gravity.CENTER);
        textView.setBackgroundColor(Color.RED);
        textView.setText("Debug");
        viewGroup.addView(textView, 200, 200);
    }
}

在Build Variants中选择不同的Variant.选中debug运行,手机上展示的是 红色背景的Debug. 选中internal运行,手机上展示的是 蓝色背景的Internal.

7. productFlavors

使用 productFlavors 必须要有 flavorDimensions . flavorDimensions指定了有多少个维度, productFlavors 指定每个维度下多个偏好.

最终的 Build Varaint 种类数量 = 维度1下偏好数量 * 维度2下偏好数量 * --- * 维度N下偏好数量 * buildType下type数量.

flavorDimensions 'price', 'nation'
productFlavors {
	//'price'维度下有2个
    free {
        dimension 'price'
    }
    paid {
        dimension 'price'
    }
    //'nation'维度下有2个
    china {
        dimension 'nation'
    }
    global {
        dimension 'nation'
    }
}

buildTypes {
	//build type 有3种
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
    debug {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
    internal {
        initWith debug
    }
}

最终可见有12中构建变体. 2*2*3 = 12 .

8. Gradle Wrapper

  • Gradle Wrapper 的作用:通过gradle-wrapper.properties记录当前项目使用的gradle版本,gradle版本的下载路径,下载完成后压缩包存放到什么路径,解压到什么路径.只要是gradle创建的项目,根据gradle-wrapper.properties文件都能被准确无误的编译执行.
  • 项目根目录下与 Gradle Wrapper 相关的几个配置文件
    ├── gradle
    │   └── wrapper
    │       ├── gradle-wrapper.jar
    │       └── gradle-wrapper.properties
    ├── gradlew
    ├── gradlew.bat
    
    • gradlew 是 Linux, Mac, 类 unix 系统上的可执行脚本.
    • gradlew.bat 是 Windows 系统上的可执行脚本.
    • gradle-wrapper.properties 文件记录着以下信息
      • 当前项目想使用的 gradle 版本
      • 去哪里下载这个版本的 gradle
      • 下载之后的压缩包保存在哪里
      • 压缩包解压到哪里
    • 当我们第一次执行 ./gradlew build 命令的时候,gradlew 会读取 gradle-wrapper.properties 文件的配置信息,准确的将指定版本的 gradle 下载并解压到指定的位置。之后执行的 ./gradlew 所有命令都是使用指定的 gradle 版本
  • 实例:
    //在空文件夹下执行 gradle wrapper.文件夹下出现了上述几个配置文件及文件夹.
    E:\Jet\***\GradleDemo1018>gradle wrapper
    BUILD SUCCESSFUL in 2s
    1 actionable task: 1 executed
    //然后执行gradlew,发现开始下载gradle-wrapper.properties中指定版本的gradle压缩包
    E:\Jet\***\GradleDemo1018>gradlew
    Downloading https://services.gradle.org/distributions/gradle-5.4.1-bin.zip
    

9. Gradle Plugin

10. Gradle报错

  1. 处理Gradle插件中groovy文件提示"class already exists"问题
    • 删除工程中所有的build目录,包括app和plugin模块.