Android Gradle开发与应用 (八) :Kotlin DSL

2024-04-14 15:04

本文主要是介绍Android Gradle开发与应用 (八) :Kotlin DSL,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 前言

本文介绍了Gradle Kotlin DSL相关的一些知识点

2. DSL是什么

DSL是为特定领域设计的专门的语言,也就是设计了一门语言,然后解决某个特定的领域的特定问题。

2.1 举例说明

以下的这些都可以称之为DSL

  • 正则表达式 :用于文本处理的特定语言
  • SQL :用于数据库查询的领域特定语言
  • HTML : 用于描述网页结构的领域特定语言
  • CSS:用于描述网页样式的领域特定语言
  • Android XML布局 : 用于描述Android页面的领域特定语言

Gradle 中的 Groovy DSL 和 Kotlin DSL 就用来编写Gradle构建脚本的领域特定语言

像Kotlin它不仅可以做一些Android开发,还可以做后端,它不属于DSL,但是我们可以通过Kotlin的一些语法规则,来开发一些特定领域的DSL语言。

2.2 Kotlin DSL

Kotlin当中的DSL,使用高阶函数和一些Lambda表达式配合来进行编写的。

对于DSL没有明确的语法规定,只要能编写出一门语言,一种语法规则,解决特定领域的问题,那么他就可以称之为DSL

Gradle构建工具现在也使用Kotlin作为Gradle的主要编写语言了。

我们去创建KotlinGradle的时候,可以发现,它里面的内容和以前的Gradle没什么区别,但是语言上是用的Kotlin。

其实就是用Kotlin写了一个专门为Gradle使用的DSL

3. kotlin-dsl是什么

在用Kotlin编写的Gradle插件中,会有kotlin-dsl这一句

plugins {`java-gradle-plugin``kotlin-dsl`
}

我们点进去可以看到kotlin-dsl中间的-不是标准的kotlin语法,所以要加上``来做区分。

public val val PluginDependenciesSpec.`kotlin-dsl`: PluginDependencySpecget() = id("org.gradle.kotlin.kotlin-dsl") version "2.4.1"

也就是说 kotlin-dsl就是PluginDependencySpec的一个扩展属性。
其实就是相当于id("org.gradle.kotlin.kotlin-dsl") version "2.4.1"

所以如果把kotlin-dsl这行代码改为id("org.gradle.kotlin.kotlin-dsl") version "2.4.1",效果是一样的。

可以在Kotlin插件项目里,全局搜索org.gradle.kotlin.kotlin-dsl

3.1 kotlin-dsl插件的作用

提供Kotlin编写Gradle脚本的能力,从而可以替代传统的Groovy语言。

  • 使用Kotlin DSL的编程风格,可以使程序更加简单干净、直观简洁。这有助于提升开发效率,降低出错的可能性,并使得构建脚本更易于理解和维护。

  • 此外,Kotlin DSL还提供了强大的类型检查和智能代码补全功能,这些功能可以进一步提高开发者的编写体验。同时,由于Kotlin语言的强大功能,Kotlin DSL也支持更复杂的构建逻辑和更灵活的脚本编写方式。

4. groovy和kotlin的语法糖

4.1 apply plugin

4.1.1 groovy中的apply plugin
apply plugin : MyPlugin

等价于

apply([plugin : MyPlugin])

当方法的参数是一个map的时候,可以将方括号[]去掉

apply(plugin: MyPlugin)

当不引起歧义的时候,可以把圆括号去掉

apply plugin : MyPlugin
4.1.2 kotlin中的apply plugin
apply(plugin = "com.android.application")

实际上也是个函数调用

public fun org.gradle.api.plugins.PluginAware.apply(from: kotlin.Any? = COMPILED_CODE, plugin: kotlin.String? = COMPILED_CODE, to: kotlin.Any? = COMPILED_CODE): kotlin.Unit {  }

4.2 gradle和kotlin中的plugins

4.2.1 groovy中的plugins
plugins {id 'com.android.application'id 'org.jetbrains.kotlin.android'
}

本质是有一个plugins的方法,调用了一个闭包
实质上是

plugins({id('com.android.application').version('8.1.3').apply(false)
})
4.2.2 kotlin中的plugins
plugins {id("com.android.application") version "8.1.3" apply false
}

本质上也就是一个函数调用

public final fun plugins(block: org.gradle.kotlin.dsl.PluginDependenciesSpecScope.() -> kotlin.Unit): kotlin.Unit { /* compiled code */ }

id方法会返回一个PluginDependencySpecPluginDependencySpec中有versionapply方法

public interface PluginDependencySpec {PluginDependencySpec version(@Nullable String version);default PluginDependencySpec version(Provider<String> version) {return this.version((String)version.get());}PluginDependencySpec apply(boolean apply);
}
4.2.3 apply plugin 和 plugins的区别
  • plugins是Gradle较新的方式,用于声明性地应用插件。有更简洁的语法,更好的插件版本控制
  • 传统的apply方法机制则更加灵活,可以动态地加载和应用插件

现在一般情况下都用plugins即可,除非是要使用build.gradle中自己写的gradle插件,采用apply plugin进行引用。

5. Groovy DSL 和 Kotlin DSL的区别

5.1 gradle中,如下Groovy和Kotlin的写法为什么会有不同 ?

比如下面的这行代码 greeting.message = 'Hi from Gradle'the<GreetingPluginExtension>().message.set("Hi from Gradle")

Gradle 中,Groovy DSLKotlin DSL 提供了不同的语法和风格来配置构建脚本。这两种语言不同的写法来配置插件扩展,是由于这两种 DSL 在语法和设计哲学上的差异造成的。

首先,来看 Groovy DSL 的写法:

greeting.message = 'Hi from Gradle'

Groovy DSL 中,插件的扩展对象通常会被添加到项目的 extensions 集合中,并且可以直接通过扩展对象的名称(在这个例子中是 greeting)来访问。Groovy 语言允许直接对属性进行赋值操作,因此可以非常方便地通过点号 . 操作符来设置属性的值。

接下来,看 Kotlin DSL 的写法:

the<GreetingPluginExtension>().message.set("Hi from Gradle")

Kotlin DSL 中,由于 Kotlin 是一种静态类型语言,它提供了更严格的类型检查和更丰富的类型系统。因此,访问插件的扩展对象需要使用 the<T>() 函数,这个函数是 Gradle Kotlin DSL 提供的一个帮助函数,用于获取指定类型的扩展对象。这样做可以提供更好的类型安全,并且使代码更加清晰和易于理解。

另外,set 方法的使用也是 Kotlin 语言特性的体现。在 Kotlin 中,属性默认是不可变的(val),如果需要修改属性的值,通常需要提供一个 set 方法。虽然 Kotlin 也支持可变属性(var),但在 Gradle Kotlin DSL 的上下文中,使用 set 方法可能是为了遵循 Gradle API 的约定,或者是为了强调这是一个设置操作。

总结来说,Groovy DSLKotlin DSL 在语法和风格上的差异导致了配置插件扩展时的不同写法。Groovy DSL 提供了更加直接和简洁的语法,而 Kotlin DSL 则强调了类型安全和清晰的代码结构。这些差异使得两种 DSL 都有其独特的优点,开发者可以根据个人喜好和项目需求选择使用哪一种。

5.2 gradle中,tasks.register(‘xxx’)和task xxx这两种新建Task方式,有什么区别 ?

在Gradle中,tasks.register('xxx')task xxx这两种方式用于新建Task, 但它们之间存在一些区别:

  1. Groovy 和 Kotlin 语法:

    • task xxx 是 Groovy 语法,它使用 Groovy 闭包来配置任务。
    • tasks.register('xxx') 是 Kotlin 语法,它通过流式 API 调用来配置任务。
  2. 任务创建时机:

    • task xxx 是在配置文件(如 build.gradle)执行期间立即创建任务的。
    • tasks.register('xxx') 可以延迟任务的创建,直到需要时才注册到任务注册表中。
  3. 可读性和维护性:

    • task xxx 的语法更接近传统的 Gradle 构建脚本,对于熟悉早期版本的 Gradle 的用户来说可能更易读。
    • tasks.register('xxx') 提供了一种更一致和流畅的任务配置方式,与 Gradle 推向的 Kotlin DSL 相契合。
  4. API 兼容性:

    • task xxx 的语法可能会在未来的 Gradle 版本中被弃用,因为 Gradle 正在推动使用 Kotlin DSL。
    • tasks.register('xxx') 是当前推荐的方式,因为它与 Gradle 的 Kotlin DSL 兼容,并且有更好的未来兼容性保证。
  5. 任务名称:

    • task xxx 中的任务名称(‘xxx’)通常不包含引号。
    • tasks.register('xxx') 中的任务名称必须包含引号。
  6. 示例:

    • 使用 task xxx 语法创建一个名为 ‘myTask’ 的任务:
      task myTask {doLast {println 'Hello from myTask!'}
      }
      
    • 使用 tasks.register('xxx') 语法创建同样的任务:
      tasks.register('myTask') {doLast {println 'Hello from myTask!'}
      }
      

总的来说,虽然 task xxxtasks.register('xxx') 都可以用来创建新的任务,但是 tasks.register 是更现代、更灵活且未来兼容的方式。随着 Gradle 的发展,推荐使用 Kotlin 语法和 tasks.register 方法进行任务创建和配置。

6. 自定android闭包

使用Kotlin DSL模拟android闭包来实现一个myandroid的闭包,将MyAndroidBean传入。

首先创建一个MyAndroidBeanDefaultConfig 传参类

class MyAndroidBean {var namespace = ""var compileSdk = 0var myDefaultConfig = DefaultConfig()fun Project.myDefaultConfig(call: DefaultConfig.() -> Unit) {val defaultConfig = DefaultConfig()defaultConfig.call()}
}class DefaultConfig {var applicationId = ""var minSdk = 0var targetSdk = 0
}

然后实现一个自定义的myandroid闭包

fun Project.myandroid(call: MyAndroidBean.() -> Unit) {val myAndroidBean = MyAndroidBean()myAndroidBean.call()val defaultConfig = myAndroidBean.myDefaultConfig//打印传参println("namespace:${myAndroidBean.namespace}")println("namespace:${myAndroidBean.compileSdk}")println("applicationId:${defaultConfig.applicationId}")println("minSdk:${defaultConfig.minSdk}")println("targetSdk:${defaultConfig.targetSdk}")
}

进行调用

myandroid {namespace = "com.heiko.mytest"compileSdk = 34myDefaultConfig {applicationId = "com.heiko.mytest"minSdk = 21targetSdk = 34}
}

7. 其他

gradle中Kotlin和Groovy的差异 :
将 build 配置从 Groovy 迁移到 Kotlin | Android Studio | Android Developers (google.cn)
Gradle Kotlin DSL 入门

Android Gradle系列文章
Android Gradle 开发与应用 (一) : Gradle基础-氦客-CSDN博客
Android Gradle开发与应用 (二) : Groovy基础语法-CSDN博客
Android Gradle开发与应用 (三) : Groovy语法概念与闭包-CSDN博客
Android Gradle开发与应用 (四) : Gradle构建与生命周期-CSDN博客
Android Gradle开发与应用 (五): 基于Gradle 8.2,创建Gradle插件-CSDN博客
Android Gradle 开发与应用 (六) : 创建buildSrc插件和使用命令行创建Gradle插件-CSDN博客
Android Gradle 开发与应用 (七) : 实现打包自动复制文件插件
Android Gradle开发与应用 (八) :Kotlin DSL

这篇关于Android Gradle开发与应用 (八) :Kotlin DSL的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/903296

相关文章

在Ubuntu上部署SpringBoot应用的操作步骤

《在Ubuntu上部署SpringBoot应用的操作步骤》随着云计算和容器化技术的普及,Linux服务器已成为部署Web应用程序的主流平台之一,Java作为一种跨平台的编程语言,具有广泛的应用场景,本... 目录一、部署准备二、安装 Java 环境1. 安装 JDK2. 验证 Java 安装三、安装 mys

Python中构建终端应用界面利器Blessed模块的使用

《Python中构建终端应用界面利器Blessed模块的使用》Blessed库作为一个轻量级且功能强大的解决方案,开始在开发者中赢得口碑,今天,我们就一起来探索一下它是如何让终端UI开发变得轻松而高... 目录一、安装与配置:简单、快速、无障碍二、基本功能:从彩色文本到动态交互1. 显示基本内容2. 创建链

基于Qt开发一个简单的OFD阅读器

《基于Qt开发一个简单的OFD阅读器》这篇文章主要为大家详细介绍了如何使用Qt框架开发一个功能强大且性能优异的OFD阅读器,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 目录摘要引言一、OFD文件格式解析二、文档结构解析三、页面渲染四、用户交互五、性能优化六、示例代码七、未来发展方向八、结论摘要

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

java中VO PO DTO POJO BO DO对象的应用场景及使用方式

《java中VOPODTOPOJOBODO对象的应用场景及使用方式》文章介绍了Java开发中常用的几种对象类型及其应用场景,包括VO、PO、DTO、POJO、BO和DO等,并通过示例说明了它... 目录Java中VO PO DTO POJO BO DO对象的应用VO (View Object) - 视图对象

在 VSCode 中配置 C++ 开发环境的详细教程

《在VSCode中配置C++开发环境的详细教程》本文详细介绍了如何在VisualStudioCode(VSCode)中配置C++开发环境,包括安装必要的工具、配置编译器、设置调试环境等步骤,通... 目录如何在 VSCode 中配置 C++ 开发环境:详细教程1. 什么是 VSCode?2. 安装 VSCo

Go信号处理如何优雅地关闭你的应用

《Go信号处理如何优雅地关闭你的应用》Go中的优雅关闭机制使得在应用程序接收到终止信号时,能够进行平滑的资源清理,通过使用context来管理goroutine的生命周期,结合signal... 目录1. 什么是信号处理?2. 如何优雅地关闭 Go 应用?3. 代码实现3.1 基本的信号捕获和优雅关闭3.2

正则表达式高级应用与性能优化记录

《正则表达式高级应用与性能优化记录》本文介绍了正则表达式的高级应用和性能优化技巧,包括文本拆分、合并、XML/HTML解析、数据分析、以及性能优化方法,通过这些技巧,可以更高效地利用正则表达式进行复杂... 目录第6章:正则表达式的高级应用6.1 模式匹配与文本处理6.1.1 文本拆分6.1.2 文本合并6

python中的与时间相关的模块应用场景分析

《python中的与时间相关的模块应用场景分析》本文介绍了Python中与时间相关的几个重要模块:`time`、`datetime`、`calendar`、`timeit`、`pytz`和`dateu... 目录1. time 模块2. datetime 模块3. calendar 模块4. timeit