1. 前言
Kotlin 是一门对 DSL 友好的语言,它的许多语法特性有助于 DSL 的打造,提升特定场景下代码的可读性和安全性。本文将带你了解 Kotlin DSL 的一般实现步骤,以及如何通过 @DslMarker
, Context Receivers
等特性提升 DSL 的易用性。
2. 什么是 DSL?
DSL 全称是 Domain Specific Language,即领域特定语言。顾名思义 DSL 是用来专门解决某一特定问题的语言,比如我们常见的 SQL 或者正则表达式等,DSL 没有通用编程语言(Java、Kotlin等)那么万能,但是在特定问题的解决上更高效。
创作一套全新新语言的成本很高,所以很多时候我们可以基于已有的通用编程语言打造自己的 DSL,比如日常开发中我们将常见到 gradle 脚本 ,其本质就是来自 Groovy 的一套 DSL:
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.my.app"
minSdkVersion 24
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
build.gradle
中我们可以用大括号表现层级结构,使用键值对的形式设置参数,没有多余的程序符号,非常直观。如果将其还原成标准的 Groovy 语法则变成下面这样,是下面这样,在可读性上的好坏立判:
Android(30,
DefaultConfig("com.my.app",
24,
30,
1,
"1.0",
"android.support.test.runner.AndroidJUnitRunner"
)
),
BuildTypes(
Release(false,
getDefaultProguardFile('proguard-android-optimize.txt'),
'proguard-rules.pro'
)
)
除了 Groovy,Kotlin 也非常适合 DSL 的书写,正因如此 Gradle 开始推荐使用 kts
替代 gradle
,其实就是利用了 Kotlin 优秀的 DSL 特性。
3. Kotlin DSL 及其优势
Kotlin 是 Android 的主要编程语言,因此我们可以在 Android 开发中发挥其 DSL 优势,提升特定场景下的开发效率。例如 Compose 的 UI 代码就是一个很好的示范,它借助 DSL 让 Kotlin 代码具有了不输于 XML 的表现力,同时还兼顾了类型安全,提升了 UI 开发效率。
普通的 Android View 也可以使用 DSL 进行描述。下面是一个简单的 UI 布局,左边是其对应的 XML 代码,右边是我们为其设计的 Kotlin DSL 代码
XML | DSL |
---|---|
通过对比可以看到 Kotin DSL 有诸多好处:
- 有着近似 XML 的结构化表现力
- 较少的字符串,更多的强类型,更安全
- 可提取 linearLayoutParams 这样的对象方便复用
- 在布局中同步嵌入 onClick 等事件处理
- 如需要还可以嵌入 if ,for 这样的控制语句
倘若没有 DSL ,我们想借助 Kotlin 达到上述好处,代码可能是下面这样的:
LinearLayout(context).apply {
addView(ImageView(context).apply {
image = context.getDrawable(R.drawable.avatar)
}, LinearLayout.LayoutParams(context, null).apply {...})
addView(LinearLayout(context).apply {
...
}, LinearLayout.LayoutParams(context,null).apply {...})
addView(Button