Kotlin 基础(二)- DSL
admin
2023-02-10 04:00:04
0

所谓 DSL 领域专用语言(Domain Specified Language/ DSL),其基本思想是“求专不求全”,不像通用目的语言那样目标范围涵盖一切软件问题,而是专门针对某一特定问题的计算机语言。

Kotlin 基础(二)- DSL

Kotlin DSL 定义:使用 Kotlin 语言开发的,解决特定领域问题,具备独特代码结构的 API 。

一、DSL

DSL(domain specific language),即领域专用语言:专门解决某一特定问题的计算机语言,比如大家耳熟能详的 SQL 和正则表达式。使用DSL的编程风格,可以让程序更加简单干净、直观简洁。当然,我们也可以创建自己的 DSL。相对于传统的 API, DSL 更加富有表现力、更符合人类语言习惯。

如果为解决某一特定领域问题就创建一套独立的语言,开发成本和学习成本都很高,因此便有了内部 DSL 的概念。所谓内部 DSL,便是使用通用编程语言来构建 DSL,比如,Kotlin DSL。

1.1 常见的 DSL

常见的 DSL 在很多领域都能看到,例如:

  • 软件构建领域 Ant
  • UI 设计师 HTML
  • 硬件设计师 VHDL
1.2 通用编程语言 vs DSL

通用编程语言(如 Java、Kotlin、Android等),往往提供了全面的库来帮助开发者开发完整的应用程序,而 DSL 只专注于某个领域,比如 SQL 仅支持数据库的相关处理,而正则表达式只用来检索和替换文本,我们无法用 SQL 或者正则表达式来开发一个完整的应用。

  • DSL 供非程序员使用,供领域专家使用;
  • DSL 有更高级的抽象,不涉及类似数据结构的细节;
  • DSL 表现力有限,其只能描述该领域的模型,而通用编程语言能够描述任意的模型;

无论是通用编程语言,还是领域专用语言,最终都是要通过 API 的形式向开发者呈现。良好的、优雅的、整洁的、一致的 API 风格是每个优秀开发者的追求,而 DSL 往往具备独特的代码结构和一致的代码风格。

二、Kotlin DSL 在 Android 开发的应用

2.1 Anko

Anko 是一个 DSL (Domain-Specific Language), 它是 JetBrains 出品的,用 Kotlin 开发的安卓框架。它主要的目的是用来替代以前 XML 的方式来使用代码生成 UI 布局。

2.1.1 使用

Anko 中, 不需要继承其他奇怪的类,只要标准的 Activity, Fragment,FragmentActivity 或者其他任意的类

首先, 在使用 Anko 的 DSL 的类中导入 org.jetbrains.anko.* .

DSL 可以在 onCreate()中使用:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    verticalLayout {
        padding = dip(30)
        editText {
            hint = "Name"
            textSize = 24f
        }
        editText {
            hint = "Password"
            textSize = 24f
        }
        button("Login") {
            textSize = 26f
        }
    }
}

不需要显示的调用 setContentView(R.layout.something), Anko 自动为 Activity(只会对Activity)进行 set content view

padding, hint 和 textSize 是 扩展属性. 大多数 View 具有这些属性,允许使用 text = “Some text” 代替 setText(“Some text”).

verticalLayout (一个竖直方向的 LinearLayout), editText 和 button

扩展函数. 这些函数存在与ANdroid 框架中的大部View中, Activities, Fragments ( android.support 包中的) 甚至 Context同样适用.

如果有一个 Context 实例, 可以写出下面的DSL结构:

val name = with(myContext) {
    editText {
        hint = "Name"
    }
}

变量 name 成为了 EditText类型.

2.1.2 Helper 方法

你可能注意到了,前面 button 方法接了一个字符串参数,这样的Helper方法同样使用与 TextView, EditText, Button , ImageView.

如果你不需要 View 其他的属性,你可以省略 {} 直接写 button(“Ok”) 或只有 button():

verticalLayout {
    button("Ok")
    button("Cancel")
}
2.1.3 Layouts 和 LayoutParams

在父布局中布局控件可能需要使用 LayoutParams.xml 中长这样:

Anko 中, 在 View 的后面使用 lparams 来实现类似与 xml 的 LayoutParams。

linearLayout {
    button("Login") {
        textSize = 26f
    }.lparams(width = wrapContent) {
        horizontalMargin = dip(5)
        topMargin = dip(10)
    }
}

如果指定了 lparams,但是没有指定 width 或者 height, 默认是 WRAP_CONTENT,但是你可以自己通过使用 named arguments指定.

注意下面一些方便的属性:

  • horizontalMargin 同时设置 left 和 right margins
  • verticalMargin 同时设置 top 和 bottom
  • margin 同时设置4个方向的 margins


    

    
    

使用 Anko 之后,可以用代码实现布局,并且 button 还绑定了点击事件。

verticalLayout {
    var title = editText {
        id = R.id.todo_title
        hintResource = R.string.title_hint
    }
    button {
        textResource = R.string.add_todo
        onClick { view -> {
                // do something here
                title.text = "Foo"
            }
        }
    }
}

可以看到 DSL 的一个主要优点在于,它需要很少的时间即可理解和传达某个领域的详细信息。

override fun onCreate(savedInstanceState: Bundle?) { 
   super.onCreate(savedInstanceState) 
   verticalLayout { 
       padding = dip(30) 
       editText { 
         hint = "Name" 
         textSize = 24f 
       } 
       editText { 
         hint = "Password" 
         textSize = 24f 
       } 
       button("Login") { 
         textSize = 26f 
       } 
   } 
 }
2.1.4 弹窗
 alert("Hi, I'm Roy", "Have you tried turning it off and on again?") { 
     yesButton { toast("Oh…") } 
     noButton {} 
 }.show()
2.1.5 异步
 doAsync { 
     // Long background task 
     uiThread { 
         result.text = "Done" 
     } 
 } 

关于我
更多信息可以点击+关于我 , 非常希望和大家一起交流 , 共同进步

相关内容

热门资讯

德国总理:美国正在被伊朗羞辱 德国之声4月27日报道,德国总理默茨在访问一所学校时表示,在当前的持续冲突中,伊朗领导层正试图羞辱美...
理响中国|“长”歌以行,风云激... 光阴如梭,东方潮阔。这里是中国的长三角,世界的长三角。无论过去、现在还是未来,这片土地都因时代而生,...
白宫:特朗普及其国安团队开会讨... 新华社华盛顿4月27日电 美国白宫新闻秘书莱维特27日在记者会上证实,总统特朗普及其国家安全团队当天...
人民日报刊文:日本放开杀伤性武... 日本放开杀伤性武器出口推高地缘冲突风险(国际论坛)常思纯《人民日报》(2026年04月28日 第 0...
医疗保障法草案二审:明确生育保... 满足多样化健康保障需求本报记者 彭 波4月27日,医疗保障法草案二审稿提请十四届全国人大常委会第二十...
天津一景区发生自转旋翼机事故1... 澎湃新闻记者 吕新文中国民用航空华北地区管理局4月22日公布《豪客通航“10•1”天津长芦汉盐旅游区...
卡塔尔埃米尔与美国总统特朗普通... 当地时间24日,卡塔尔埃米尔塔米姆与美国总统特朗普通电话,重点就中东地区局势以及伊朗与美国谈判问题交...
男子30年前被扣押2859克黄... 澎湃新闻记者 王鑫家住辽宁省大连市的潘永嘉近日向澎湃新闻反映称,三十年前,他在大连周水子机场被盖州市...
商务部:取消反制欧盟两家金融机... 中华人民共和国商务部令二〇二六年 第1号鉴于欧盟已取消对中国两家金融机构的制裁措施,现公布《关于取消...
过去24小时共有5艘船只通过霍... 总台记者当地时间24日获悉,过去24小时内,共有5艘船只通过霍尔木兹海峡,其中包括一艘伊朗油轮。(总...