Kotlin技术-编写gradle脚本

  • Post author:
  • Post category:其他




1. 为什么不用Groovy编写Gradle脚本



动态语言 VS 静态语言

静态语言编译器有代码提示,编译的代码更健壮

静态语言 是指在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型。例如:C++、Java、Delphi、C#、 kotlin 等。

动态语言 是在运行时确定数据类型的语言。变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型。例如:Python、Ruby、Perl,groovy, javascript等。

所以我把build.gradle 该成

kts

后缀之后, 再添加代码库时,我们会发现,有提示了

在这里插入图片描述



2. Gradle 基础知识

Gradle 本身的领域对象主要有Project和Task

Project 为Task 提供了执行的容器和上下文



1 project

看源码发现,project(工程)是 org.gradle.api 定义的一个接口,gradle之所以能够工作,是因为在gradle编写的代码,会以任务的方式插入到project里面,project会执行我们编写的任务(task)。project提供了任务执行的环境和上下文。 安卓程序员来看,像是一个上下文(Context)的功能。

在这里插入图片描述



2 task

Task(任务)就是执行在 project里面的,是一个一个的小模块。个人理解像Kotlin里面的扩展函数。



3 HelloWorld
  1. 我们把 build.gradle.kts 里面默认生成的代码全删掉,添加下面的代码
task("HelloWorld") {
    println("HelloWorld")
}
  1. 按一下步骤找到任务 HelloWorld 双击运行。如果没有HelloWorld,就点下同步,编译一下。

    在这里插入图片描述
  2. 控制台会出现一面的打印,我们看到执行结果跟普通代码里没有什么两样,正常打印。

在这里插入图片描述



4 把大象放冰箱里
task("openDoor") {
    println("openDoor ")
}

task("putElephant") {
    println("putElephant ")
}

task("closeDoor") {
    println("closeDoor ")
}

运行结果:

在这里插入图片描述

dependsOn (任务的依赖):执行当前任务前 要先执行,dependsOn里面的内容 ,所以就可以顺序执行了

task("openDoor") {
    println("openDoor ")
}
task("putElephant") {
    println("putElephant ")
}.dependsOn("openDoor")// 

task("closeDoor") {
    println("closeDoor ")
}.dependsOn("putElephant")

但是如果我们把代码顺序换一下

task("closeDoor") {
    println("closeDoor ")
}.dependsOn("putElephant")

task("putElephant") {
    println("putElephant ")
}.dependsOn("openDoor")

task("openDoor") {
    println("openDoor ")
}

运行结果: 打印结果的顺序与代码书写的先后一致。 那么,为什么dependsOn 没有起作用呢。

在这里插入图片描述



Tesk的生命周期(扫描和执行)

gradle 对脚本文件进行构建的时候,首先会扫描下,会对任务里闭包(花括号,蓝不打表达式)里声明的逻辑执行一下。所以上面代码是段声明式代码。 其实上面代码执行的顺序是 编译器扫面的顺序,如果我们想只有在执行时才打印呢?



doFirst / doLast 任务执行时才运行闭包里声明的代码
task("closeDoor") {
    doLast() {
        println("over ")
    }
    doFirst {
        println("closeDoor ")
    }
}.dependsOn("putElephant")

task("putElephant") {
    doFirst {
        println("putElephant ")
    }
}.dependsOn("openDoor")

task("openDoor") {
    doFirst {
        println("openDoor ")
    }
}


运行结果: 一个任务 一个逻辑,可以对比上面运行结果对比。

在这里插入图片描述



3. Gradle 任务集 Tasks

多任务的集合就是任务集

tasks() {
    task("closeDoor") {
        doLast {
            println("over ")
        }
        doFirst {
            println("closeDoor ")
        }
    }.dependsOn("putElephant")

    task("putElephant") {
        doFirst {
            println("putElephant ")
        }
    }.dependsOn("openDoor")

    task("openDoor") {
        doFirst {
            println("openDoor ")
        }
    }
}



4. Gradle 默认任务



1.properties 默认属性

task("plProperties") {
    project.properties.forEach {
        println("key: ${it.key}  --  value: ${it.value}")
    }
}

运行结果:


> Configure project :
key: parent  --  value: null
key: classLoaderScope  --  value: org.gradle.api.internal.initialization.DefaultClassLoaderScope@285a2c48
key: buildDir  --  value: D:\IdeaProjects\untitled\build
key: configurations  --  value: configuration container
key: plugins  --  value: [org.gradle.api.plugins.HelpTasksPlugin@50aaf35f, org.gradle.buildinit.plugins.BuildInitPlugin@15b795bf, org.gradle.buildinit.plugins.WrapperPlugin@7e56c267, org.gradle.kotlin.dsl.provider.plugins.KotlinScriptRootPlugin@51df3340, org.gradle.kotlin.dsl.provider.plugins.KotlinScriptBasePlugin@56e8022f]
key: scriptHandlerFactory  --  value: org.gradle.api.internal.initialization.DefaultScriptHandlerFactory@7fdb7f20
key: gradleKotlinDsl.projectAccessorsClassPath  --  value: AccessorsClassPath(bin=[C:\Users\android\.gradle\caches\5.6.4\gradle-kotlin-dsl-accessors\592kebbqpm8qse0akhhq6udie\cache\classes], src=[C:\Users\android\.gradle\caches\5.6.4\gradle-kotlin-dsl-accessors\592kebbqpm8qse0akhhq6udie\cache\src])
key: objects  --  value: org.gradle.api.internal.model.DefaultObjectFactory@37d6cf46
key: logger  --  value: org.gradle.internal.logging.slf4j.OutputEventListenerBackedLogger@680906b3
key: deferredProjectConfiguration  --  value: org.gradle.api.internal.project.DeferredProjectConfiguration@1f3bbfcf
key: rootDir  --  value: D:\IdeaProjects\untitled
key: project  --  value: root project 'untitled'
key: projectRegistry  --  value: org.gradle.api.internal.project.DefaultProjectRegistry@9d42f7d
key: path  --  value: :
key: normalization  --  value: org.gradle.normalization.internal.DefaultInputNormalizationHandler_Decorated@2d526318
key: repositories  --  value: repository container
key: childProjects  --  value: {}
key: scriptPluginFactory  --  value: org.gradle.configuration.ScriptPluginFactorySelector@2c7f350b
key: state  --  value: project state 'EXECUTING'
key: resourceLoader  --  value: org.gradle.internal.resource.transfer.DefaultUriTextResourceLoader@6ef8228c
key: plProperties  --  value: task ':plProperties'
key: serviceRegistryFactory  --  value: org.gradle.internal.service.scopes.ProjectScopeServices$4@467f57e9
key: tasks  --  value: task set
key: group  --  value: 
key: artifacts  --  value: org.gradle.api.internal.artifacts.dsl.DefaultArtifactHandler_Decorated@788ba69d
key: ext  --  value: org.gradle.internal.extensibility.DefaultExtraPropertiesExtension@2d0913ea
key: projectDir  --  value: D:\IdeaProjects\untitled
key: dependencyLocking  --  value: org.gradle.internal.locking.DefaultDependencyLockingHandler_Decorated@2cab885
key: configurationTargetIdentifier  --  value: org.gradle.configuration.ConfigurationTargetIdentifier$1@3e36672a
key: projectEvaluationBroadcaster  --  value: ProjectEvaluationListener broadcast
key: projectPath  --  value: :
key: module  --  value: org.gradle.api.internal.artifacts.ProjectBackedModule@1027e025
key: inheritedScope  --  value: org.gradle.internal.extensibility.ExtensibleDynamicObject$InheritedDynamicObject@1bac913f
key: version  --  value: unspecified
key: script  --  value: false
key: dependencies  --  value: org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler_Decorated@7e5f47e3
key: fileResolver  --  value: org.gradle.api.internal.file.BaseDirFileResolver@2906d63d
key: extensions  --  value: org.gradle.api.internal.plugins.DefaultConvention@2484eb00
key: kotlin.code.style  --  value: official
key: modelRegistry  --  value: org.gradle.model.internal.registry.DefaultModelRegistry@5bdeb3c6
key: projectEvaluator  --  value: org.gradle.configuration.project.LifecycleProjectEvaluator@5f3a9701
key: projectConfigurator  --  value: org.gradle.api.internal.project.BuildOperationCrossProjectConfigurator@409215e5
key: name  --  value: untitled
key: logging  --  value: org.gradle.internal.logging.services.DefaultLoggingManager@43cd2a1c
key: configurationActions  --  value: org.gradle.configuration.project.DefaultProjectConfigurationActionContainer@6da3f120
key: buildscript  --  value: org.gradle.api.internal.initialization.DefaultScriptHandler@66aaf10a
key: status  --  value: release
key: processOperations  --  value: org.gradle.process.internal.DefaultExecActionFactory$DecoratingExecActionFactory@3647fd07
key: subprojects  --  value: []
key: components  --  value: SoftwareComponentInternal set
key: asDynamicObject  --  value: DynamicObject for root project 'untitled'
key: displayName  --  value: root project 'untitled'
key: identityPath  --  value: :
key: parentIdentifier  --  value: null
key: description  --  value: null
key: antBuilderFactory  --  value: org.gradle.api.internal.project.DefaultAntBuilderFactory@1c70bc19
key: buildPath  --  value: :
key: fileOperations  --  value: org.gradle.api.internal.file.DefaultFileOperations@6ea86446
key: pluginManager  --  value: org.gradle.api.internal.plugins.DefaultPluginManager_Decorated@5fbbfa38
key: standardOutputCapture  --  value: org.gradle.internal.logging.services.DefaultLoggingManager@43cd2a1c
key: defaultTasks  --  value: []
key: modelSchemaStore  --  value: org.gradle.model.internal.manage.schema.extract.DefaultModelSchemaStore@6c61715
key: class  --  value: class org.gradle.api.internal.project.DefaultProject_Decorated
key: buildScriptSource  --  value: org.gradle.groovy.scripts.TextResourceScriptSource@569d8b0d
key: convention  --  value: org.gradle.api.internal.plugins.DefaultConvention@2484eb00
key: allprojects  --  value: [root project 'untitled']
key: baseClassLoaderScope  --  value: org.gradle.api.internal.initialization.DefaultClassLoaderScope@4f9465b3
key: ant  --  value: org.gradle.api.internal.project.DefaultAntBuilder@62b3a253
key: resources  --  value: org.gradle.api.internal.resources.DefaultResourceHandler@62d9fe07
key: services  --  value: ProjectScopeServices
key: gradle  --  value: build 'untitled'
key: layout  --  value: org.gradle.api.internal.file.DefaultProjectLayout@58a6d4b2
key: buildFile  --  value: D:\IdeaProjects\untitled\build.gradle.kts
key: depth  --  value: 0
key: mutationState  --  value: project :
key: listenerBuildOperationDecorator  --  value: org.gradle.configuration.internal.DefaultListenerBuildOperationDecorator@34738be8
key: rootProject  --  value: root project 'untitled'
key: properties  --  value: {parent=null, classLoaderScope=org.gradle.api.internal.initialization.DefaultClassLoaderScope@285a2c48, buildDir=D:\IdeaProjects\untitled\build, configurations=configuration container, plugins=[org.gradle.api.plugins.HelpTasksPlugin@50aaf35f, org.gradle.buildinit.plugins.BuildInitPlugin@15b795bf, org.gradle.buildinit.plugins.WrapperPlugin@7e56c267, org.gradle.kotlin.dsl.provider.plugins.KotlinScriptRootPlugin@51df3340, org.gradle.kotlin.dsl.provider.plugins.KotlinScriptBasePlugin@56e8022f], scriptHandlerFactory=org.gradle.api.internal.initialization.DefaultScriptHandlerFactory@7fdb7f20, gradleKotlinDsl.projectAccessorsClassPath=AccessorsClassPath(bin=[C:\Users\android\.gradle\caches\5.6.4\gradle-kotlin-dsl-accessors\592kebbqpm8qse0akhhq6udie\cache\classes], src=[C:\Users\android\.gradle\caches\5.6.4\gradle-kotlin-dsl-accessors\592kebbqpm8qse0akhhq6udie\cache\src]), objects=org.gradle.api.internal.model.DefaultObjectFactory@37d6cf46, logger=org.gradle.internal.logging.slf4j.OutputEventListenerBackedLogger@680906b3, deferredProjectConfiguration=org.gradle.api.internal.project.DeferredProjectConfiguration@1f3bbfcf, rootDir=D:\IdeaProjects\untitled, project=root project 'untitled', projectRegistry=org.gradle.api.internal.project.DefaultProjectRegistry@9d42f7d, path=:, normalization=org.gradle.normalization.internal.DefaultInputNormalizationHandler_Decorated@2d526318, repositories=repository container, childProjects={}, scriptPluginFactory=org.gradle.configuration.ScriptPluginFactorySelector@2c7f350b, state=project state 'EXECUTING', resourceLoader=org.gradle.internal.resource.transfer.DefaultUriTextResourceLoader@6ef8228c, plProperties=task ':plProperties', serviceRegistryFactory=org.gradle.internal.service.scopes.ProjectScopeServices$4@467f57e9, tasks=task set, group=, artifacts=org.gradle.api.internal.artifacts.dsl.DefaultArtifactHandler_Decorated@788ba69d, ext=org.gradle.internal.extensibility.DefaultExtraPropertiesExtension@2d0913ea, projectDir=D:\IdeaProjects\untitled, dependencyLocking=org.gradle.internal.locking.DefaultDependencyLockingHandler_Decorated@2cab885, configurationTargetIdentifier=org.gradle.configuration.ConfigurationTargetIdentifier$1@3e36672a, projectEvaluationBroadcaster=ProjectEvaluationListener broadcast, projectPath=:, module=org.gradle.api.internal.artifacts.ProjectBackedModule@1027e025, inheritedScope=org.gradle.internal.extensibility.ExtensibleDynamicObject$InheritedDynamicObject@1bac913f, version=unspecified, script=false, dependencies=org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler_Decorated@7e5f47e3, fileResolver=org.gradle.api.internal.file.BaseDirFileResolver@2906d63d, extensions=org.gradle.api.internal.plugins.DefaultConvention@2484eb00, kotlin.code.style=official, modelRegistry=org.gradle.model.internal.registry.DefaultModelRegistry@5bdeb3c6, projectEvaluator=org.gradle.configuration.project.LifecycleProjectEvaluator@5f3a9701, projectConfigurator=org.gradle.api.internal.project.BuildOperationCrossProjectConfigurator@409215e5, name=untitled, logging=org.gradle.internal.logging.services.DefaultLoggingManager@43cd2a1c, configurationActions=org.gradle.configuration.project.DefaultProjectConfigurationActionContainer@6da3f120, buildscript=org.gradle.api.internal.initialization.DefaultScriptHandler@66aaf10a, status=release, processOperations=org.gradle.process.internal.DefaultExecActionFactory$DecoratingExecActionFactory@3647fd07, subprojects=[], components=SoftwareComponentInternal set, asDynamicObject=DynamicObject for root project 'untitled', displayName=root project 'untitled', identityPath=:, parentIdentifier=null, description=null, antBuilderFactory=org.gradle.api.internal.project.DefaultAntBuilderFactory@1c70bc19, buildPath=:, fileOperations=org.gradle.api.internal.file.DefaultFileOperations@6ea86446, pluginManager=org.gradle.api.internal.plugins.DefaultPluginManager_Decorated@5fbbfa38, standardOutputCapture=org.gradle.internal.logging.services.DefaultLoggingManager@43cd2a1c, defaultTasks=[], modelSchemaStore=org.gradle.model.internal.manage.schema.extract.DefaultModelSchemaStore@6c61715, class=class org.gradle.api.internal.project.DefaultProject_Decorated, buildScriptSource=org.gradle.groovy.scripts.TextResourceScriptSource@569d8b0d, convention=org.gradle.api.internal.plugins.DefaultConvention@2484eb00, allprojects=[root project 'untitled'], baseClassLoaderScope=org.gradle.api.internal.initialization.DefaultClassLoaderScope@4f9465b3, ant=org.gradle.api.internal.project.DefaultAntBuilder@62b3a253, resources=org.gradle.api.internal.resources.DefaultResourceHandler@62d9fe07, services=ProjectScopeServices, gradle=build 'untitled', layout=org.gradle.api.internal.file.DefaultProjectLayout@58a6d4b2, buildFile=D:\IdeaProjects\untitled\build.gradle.kts, depth=0, mutationState=project :, listenerBuildOperationDecorator=org.gradle.configuration.internal.DefaultListenerBuildOperationDecorator@34738be8, rootProject=root project 'untitled', properties=(this Map), providers=org.gradle.api.internal.provider.DefaultProviderFactory@751937c9}
key: providers  --  value: org.gradle.api.internal.provider.DefaultProviderFactory@751937c9

> Task :plProperties UP-TO-DATE

BUILD SUCCESSFUL in 55ms



2. defaultTasks

把任务添加到默认任务里时,通过命令行执行时 直接写 gradle 就可以了,前提时你的电脑配置了gradle的环境变量.

task("plProperties") {
    project.properties.forEach {
        println("key: ${it.key}  --  ${it.value}")
    }
}

defaultTasks("plProperties")



5. Gradle 增量式更新 (UP-TO-DATE)

gradle 执行效率为什么时Maven的100倍. 就是因为 增量更新. 简单一句话就是在编译的时候,观察哪个文件变化了才去编译哪个文件,如果没有变化,就不再编译. 牺牲空间,节省时间



模仿打包时,gradle扫描源代码

基础代码: 会在项目根目录下生成一个 info.txt 文件, 内容都是src下的文件的全路径

plugins {
    java
}
task("getSrcName") {
    doFirst {
        var infoTxt = file("info.txt")
        var srcDir = fileTree("src")
        srcDir.forEach {
            if (it.isFile) {
             	Thread.sleep(1000)
                infoTxt.appendText(it.absolutePath)
                infoTxt.appendText(" \r\n ")
            }
        }
    }
}

运行时间: 5s

不断双击任务: 会不断追写文件
在这里插入图片描述



用到的指令: inputs.dir() / inputs.file() / outputs.dir() / outputs.file

修改后

plugins {
    java
}
task("getSrcName") {
    // 如果被观察的输入输出都没有变化 这个任务就不会再执行了
    inputs.dir("src") // 构建任务的输入
    outputs.files("info.txt")// 构建任务的输出
    doFirst {
        var infoTxt = file("info.txt")
        var srcDir = fileTree("src")
        srcDir.forEach {
            if (it.isFile) {
                Thread.sleep(1000)
                infoTxt.appendText(it.absolutePath)
                infoTxt.appendText(" \r\n ")
            }
        }
    }
}

第一次运行时间: 5s

在这里插入图片描述

第二次运行时间: 56ms (1 actionable task: 1

up-to-date

) 新的重复的没有变化的文件,不再执行

在这里插入图片描述

修改src下的某一个代码文件

第三次运行时间: 5秒

在这里插入图片描述



6. Gradle 常用插件



application插件

plugins {
    application
}
application {
    mainClassName = "Test"
}
public class Test {
    public static void main(String[] args) {
        System.out.println("Hello");
    }
}



war插件



java插件



kotlin插件



版权声明:本文为zhf6751134原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。