草庐IT

在 Android 中掌握 Kotlin DSL

Darren老师 2023-03-28 原文

前言

在这篇文章中,我们将学习如何在您的 Android 项目中编写 Kotlin DSL。

这个文章会很长,所以花点时间,让我们一起来写你的 DSL。我们将讨论以下主题,

  • 什么是简单英语中的 DSL?
  • 您使用任何 DSL 吗?
  • 为什么我们使用 DSL?
  • 我们如何编写自己的 DSL
  • 基本示例说明。

那么让我们开始吧。

什么是 DSL?

维基百科的定义说,

领域特定语言( DSL) 是专门针对特定应用领域的计算机语言。这与广泛适用于跨领域的通用语言(GPL)形成对比。

喜欢认真吗?

一般而言,DSL 为您提供了任何特定语言的灵活工具,以利用特定编程语言提供的功能。

您使用任何 DSL 吗?

如果您是一名 android 开发人员并且在您的项目中使用 kotlin,您可能会有意或无意地在您的项目中使用 DSL?你能想出一个例子吗?

让我帮你,你有没有写过类似的代码,

yourlist.forEach { 
    //your code is here
}

上面的例子是在 Kotlin 的列表中使用forEach。forEach is kotlin 是 DSL 的一个例子

为什么我们使用 DSL?

我们应该使用 DSL 来简化和提高应用程序的复杂性,并使代码更具可读性。

我们如何编写自己的 DSL?

在开始编写我们自己的 DSL 之前,我们需要了解带有接收器的 lambda。
但也让我简要概述一下 lambda with receiver

假设我们有一个函数 buildString,

fun buildString(action: (StringBuilder).() -> Unit): String {
    val stringBuilder = StringBuilder()
    action(stringBuilder)
    return stringBuilder.toString()
}

在这里,我们有一个函数buildString,它将动作(它是一个函数)作为参数。此处的action函数以StringBuilder作为参数,函数buildString以 String 作为返回类型。

现在,要使用我们编写的buildString ,

buildString {
    append("<")
    append("MindOrks")
    append(">")
}

我们在这里使用 Kotlin 的属性来传递与 StringBuilder 相关的属性,因为我们在buildString函数中使用了扩展函数的强大功能。

我们还可以使用创建自定义 DSL,

中缀

在 Kotlin 中,中缀帮助我们创建自定义 DSL,类似于我们用英语编写的方式。例如,

在英语中,我们说“1加2”来求和或求差,我们说“1减2”。使用中缀调用可以在 Kotin 中实现类似的事情。

为了创建一个中缀来添加我们使用的数字,

infix fun Int.plus(number: Int) = this + number

在这里,我们创建了一个 Int 的扩展函数,加上它接受一个数字并返回这个 + 数字的总和。这是应用函数的数字。

所以,要使用我们使用的这个中缀函数,

val output = 1 plus 2

在上面的代码中,我们使用我们创建加号的中缀函数来生成输出。当我们在 Logcat 中打印它时,它会打印3作为总和。

这是因为我们创建了一个中缀扩展函数来使用加号文本代替“ + ”,我们将其用作传统方式。

同样,如果我们想让中缀函数减号,我们使用

infix fun Int.minus(number: Int) = this - number

为了使用它,我们使用,

val output = 1 minus 2

中缀使代码具有可读性并且非常有序,任何人都可以阅读。因此,如果任何对编程一无所知的人也可以说这是对两个数字进行加法或减法。

调用

在调用中,运算符允许将任何对象作为函数调用。在这里,让我们创建一个名为Student的类,

class Student {
    operator fun invoke(student: Student.() -> Unit) = student
    fun addName(name: String) {
        //implementation
    }
    fun addMarks(marks: Int) {
        //implementation
    }
}

在类中,我们创建了一个函数调用,它接受一个学生类型的参数并返回学生本身。所以,这里我们可以在student本身的对象中使用Student类的所有方法。

现在,要使用 Class,我们仍然会像在 Kotlin 中一样创建对象,

val student = Student()

现在你可以看到我们有另一个函数叫做addName addMarks**我们将把它用作 DSL。但是,在这里我们可以以两种不同的方式使用它。两者如下,

  1. 类型 - 1(传统方式)
student.addName("MindOrks")
student.addMarks(100)

上面的代码就像我们以前在 Android 中做的旧的传统方式。2.DSL方式

student {
    addName("MindOrks")
    addMarks(100)
}

在这里,我们使用 Kotlin DSL。如果你注意到了,我们有类似的 lambda,

Student.() -> Unit

如果你注意到了,我们在那里有一个.()。它指定 lambda 有一个接收器,要使用它,我们需要创建一个类的构造。这就是您可以使用调用来创建 DSL 的方式。

通过以上方式,您可以在 Kotlin 中创建您赢得的 DSL。

现在,让我们讨论 Android 中 DSL 的用例和示例。

  1. 数据类

在此,让我们讨论如何创建数据类的 DSL。考虑我们有一个数据类 Student

data class Student(
    var name: String? = null,
    var age: Int? = null,
    var marks: Int? = null
)

在此,如果我们使用我们编写的数据类,

val student =  Student(
      "MindOrks",
      20,
      30
  )

现在要在 DSL 中转换上述代码,

现在我们将创建一个新的 lambda,如下所示,

fun student(student: Student.() -> Unit): Student = Student().apply(student)

在上面的代码中,

我们有一个接收器,参数为 student 并将其用作我们使用的 DSL,

val student = student {
    name = "MindOrks"
    age = 20
    marks = 30
}

这就是我们可以将数据类转换为 DSL 的方法。

  1. UI 元素

为此,让我们将 textView 视为 UI 元素。在那,我们使用如下,

textView.text = "MindOrks"
textView.setOnClickListener {  
    
} 
textView.setTextColor(Color.BLACK)

但是要通过我们使用的 DSL 使用它,

textView.apply {
    text = "MindOrks"
    setOnClickListener {

    }
    textColor(Color.BLACK)
}

我们使用apply在任何 UI元素中创建 DSL

  1. JSON

在我们使用的 Android 中创建 JSON,

val jsonObject = JSONObject()
jsonObject.put("name","MindOrks")
jsonObject.put("age",20)

这是创建 JSON 对象的传统方式。

现在,让我们看看如何创建 DSL 来创建 JSON。首先,我们将创建一个类并使用 JSONObject() 对其进行扩展,

class Json() : JSONObject() {

}

现在,我们将使用带有接收器的 lambda 构造函数

constructor(json: Json.() -> Unit) : this() {
    this.init()
}

将使用中缀创建一个泛型来向 JSON 对象添加值。

看起来像,

infix fun <T> String.to(value: T) {
    put(this, value)
}

在这里,它将使用字符串键放置值,而值将使用“ to”的类型。

现在,完整的类文件看起来像,

class Json() : JSONObject() {

    constructor(json: Json.() -> Unit) : this() {
        this.json()
    }

    infix fun <T> String.to(value: T) {
        put(this, value)
    }
}
为了在 Activity 文件中使用它,我们使用刚刚创建的 DSL 创建 JSON,

val json = Json {
    "name" to "MindOrks"
    "age" to 20
}

这里,

  • to是我们为将值放入 JSON 对象而创建的中缀。
  • JSON 是我们创建的类,它使用键和值来创建 JSON 对象。

当我们在 Logcat 中打印它时,我们得到以下输出,

{"name":"MindOrks","age":20}

这就是您可以在 kotlin 代码中创建 DSL 的方式。

作者:Himanshu Singh
链接:https://blog.mindorks.com/mastering-kotlin-dsl-in-android-step-by-step-guide

有关在 Android 中掌握 Kotlin DSL的更多相关文章

  1. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  2. 一文让你彻底掌握操作符(超详细教程) - 2

    ✅作者简介:大家好,我是小杨📃个人主页:「小杨」的csdn博客🔥系列专栏:小杨带你玩转C语言【初阶】🐳希望大家多多支持🥰一起进步呀!大家好呀!我是小杨。小杨花几天的时间将C语言中的操作符这部分知识做了一个大总结,在方便自己复习的同时也能够帮助到大家。通篇字数在一万字左右,可以算作是非常详细了,一文就可以带领大家彻底掌握操作符这部分内容,文章很长建议先收藏再看,防止下次想看就找不到啦。文章目录✍1,算术操作符✍2,移位操作符    🔍2.1,左移操作符    🔍2.2,右移操作符       ✨2.2.1,算术移位       ✨2.2.2,逻辑移位✍3,位操作符    🔍3.1,按位与&   

  3. Android Studio开发之使用内容组件Content获取通讯信息讲解及实战(附源码 包括添加手机联系人和发短信) - 2

    运行有问题或需要源码请点赞关注收藏后评论区留言一、利用ContentResolver读写联系人在实际开发中,普通App很少会开放数据接口给其他应用访问。内容组件能够派上用场的情况往往是App想要访问系统应用的通讯数据,比如查看联系人,短信,通话记录等等,以及对这些通讯数据及逆行增删改查。首先要给AndroidMaifest.xml中添加响应的权限配置 下面是往手机通讯录添加联系人信息的例子效果如下分成三个步骤先查出联系人的基本信息,然后查询联系人号码,再查询联系人邮箱代码 ContactAddActivity类packagecom.example.chapter07;importandroid

  4. Android 10.0 设置默认launcher后安装另外launcher后默认Launcher失效的功能修复 - 2

    1.前言 在10.0的系统rom定制化开发中,在系统中有多个launcher的时候,会在开机进入launcher的时候弹窗launcher列表,让用户选择进入哪个launcher,这样显得特别的不方便所以产品开发中,要求用RoleManager的相关api来设置默认Launcher,但是在设置完默认Launcher以后,在安装一款Launcher的时候,默认Launcher就会失效,在系统设置的默认应用中Launcher选项就为空,点击home键的时候会弹出默认Launcher列表,让选择进入哪个默认Launcher.所以需要从安装Launcher的流程来分析相关的设置。来解决问题设置默认La

  5. AiBote 2022 新研发的自动化框架,支持 Android 和 Windows 系统。速度非常快 - 2

    Ai-Bot基于流行的Node.js和JavaScript语言的一款新自动化框架,支持Windows和Android自动化。1、Windowsxpath元素定位算法支持支持Windows应用、.NET、WPF、Qt、Java和Electron客户端程序和ie、edgechrome浏览器2、Android支持原生APP和H5界面,元素定位速度是appium十倍,无线远程自动化操作多台安卓设备3、基于opencv图色算法,支持找图和多点找色,1080*2340全分辨率找图50MS以内4、内置免费OCR人工智能技术,无限制获取图片文字和找字功能。5、框架协议开源,除官方node.jsSDK外,用户可

  6. Android Gradle 7.1+新版本依赖变化 - 2

    前一段时间由于工作需要把可爱的小雪狐舍弃了,找到了小蜜蜂。但是新版本的小蜜蜂出现了很多和旧版本不一样的位置。1.功能位置迁移,原来在工程build.gradle的buildscript和allprojects移动至setting.gradle并改名为pluginManagement和dependencyResolutionManagement。里面的东西依旧可以按照原来的copy过来。pluginManagement{repositories{gradlePluginPortal()google()mavenCentral()}}dependencyResolutionManagement{r

  7. ruby - Ruboto 的最佳教程(适用于 Android 的 ruby​​)? - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于StackOverflow来说是偏离主题的,因为它们往往会吸引自以为是的答案和垃圾邮件。相反,describetheproblem以及迄今为止为解决该问题所做的工作。关闭9年前。Improvethisquestion我几乎用完了Ruby,但现在想试试Ruboto,android上的ruby​​。谷歌未能给我足够的(几乎没有结果)。所以任何人都可以分享一些关于Ruboto的教程。

  8. Android Studio 解决Could not resolve com.android.tools.build:gradle:7.4.2问题 - 2

    Aproblemoccurredconfiguringrootproject'MyApplication2'.>Couldnotresolveallfilesforconfiguration':classpath'.  >Couldnotresolvecom.android.tools.build:gradle:7.4.2.   Requiredby:     project:>com.android.application:com.android.application.gradle.plugin:7.4.2     project:>com.android.library:com.andr

  9. Android对话框的详细介绍(提示对话框,自定义对话框) - 2

    简介:我们都知道在Android开发中,当我们的程序在与用户交互时,用户会得到一定的反馈,其中以对话框的形式的反馈还是比较常见的,接下来我们来介绍几种常见的对话框的基本使用。前置准备:(文章最后附有所有代码)我们首先先写一个简单的页面用于测试这几种Dialog(对话框)代码如下,比较简单,就不做解释了一、提示对话框(即最普通的对话框)首先我们给普通对话框的按钮设置一个点击事件,然后通过AlertDialog.Builder来构造一个对象,为什么不直接Dialog一个对象,是因为Dialog是一个基类,我们尽量要使用它的子类来进行实例化对象,在实例化对象的时候,需要将当前的上下文传过去,因为我这

  10. 一、51单片机 使用Proteus掌握LCD1602显示屏的使用(仿真及代码) - 2

    1、单片机控制液晶显示模块1602LCD的显示。液晶显示器(LiquidCrystalDisplay,LCD)具有省电、体积小、抗干扰能力强等优点,LCD显示器分为字段型、字符型和点阵图形型。(1)字段型。以长条状组成字符显示,主要用于数字显示,也可用于显示西文字母或某些字符,广泛用于电子表、计算器、数字仪表中。(2)字符型。专门用于显示字母、数字、符号等。一个字符由5、7或5、10的点阵组成,在单片机系统中已广泛使用(3)点阵图形型。广泛用于图形显示,如笔记本电脑、彩色电视和游戏机等。它是在平板上排列的多行列的矩阵式的晶格点,点大小与多少决定了显示的清晰度。引脚包括8条数据线、3条控制线和3

随机推荐