kotlin dsl
在Android中,每门教您基础知识的教程都描述了如何通过XML文件设计屏幕。 使用Java(或任何基于JVM的语言)也可以达到相同的结果。 Android屏幕设计并不是XML和Java是有效选项的唯一领域。 例如,Spring配置和Vaadin屏幕设计都可以。 然而,在所有这些领域中,都需要权衡取舍:一方面,XML具有由XML模式强制执行的相当僵化的结构,而Java却以牺牲可读性为代价提供了执行任何操作的能力。 “拥有权利的同时也被赋予了重大的责任”。 在后一种情况下,由单个开发人员来行使他/她的判断,以便使代码尽可能地可读。
领域特定的语言位于频谱的这两端之间,因为它们提供了一种结构化的语法,可以解决当前的问题,但在必要时会完全支持基础语言结构。 例如,AssertJ库使用流利的API为声明提供DSL。 以下摘录来自其文档:
// entry point for all assertThat methods and utility methods (e.g. entry)
importstaticorg.assertj.core.api.Assertions.*;
// collection specific assertions (there are plenty more)
// in the examples below fellowshipOfTheRing is a List<TolkienCharacter>
assertThat(fellowshipOfTheRing).hasSize(9)
.contains(frodo,sam)
.doesNotContain(sauron);
DSL可以以任何语言提供,即使有些人感觉更自然。 自然地会想到Scala,但Kotlin也非常适合。 回到Android,Jetbrains提供了出色的Anko库,可以使用基于Kotlin的DSL设计Android屏幕。 以下代码片段突出显示了Anko(摘自文档):
verticalLayout{
valname=editText()
button("Say Hello"){
onClick{toast("Hello, ${name.text}!")}
}
}
为此需要两种Kotlin语言构造。
扩展功能
我已经写过关于扩展功能的文章,所以我会很快介绍它。 本质上, 扩展功能是向现有类型添加行为的一种方式。
例如, String
具有设置大小写的方法,但是没有大写字母。 使用扩展功能,很容易就能填补空白:
funString.toCapitalCase()=when{
length<2->toUpperCase()
else->this[0].toUpperCase()+substring(1).toLowerCase()
}
此时,用法很简单: "foo".toCapitalCase()
。
最重要的一点就是使用this
在上面的代码片段:它指的是实际的字符串实例。
功能类型
在Kotlin中,功能是类型。 在所有后果中,这意味着可以将函数作为函数参数进行传递。
fundoSomethingWithInt(value:Int,f:(Int)->Unit){
value.apply(f);
}
上面的函数现在可以传递给任何将Int
作为参数并返回Unit
函数, 例如 { print(it) }
。 这样称呼:
doSomethingWithInt(5,{print(it)})
现在,Kotlin在调用方法时提供了语法糖:如果lambda是函数调用中的最后一个参数,则可以将其与其他参数分开,如下所示:
doSomethingWithInt(5){print(it)}
放在一起
inlinefunViewManager.verticalLayout(theme:Int=0,init:_LinearLayout.()->Unit):LinearLayout{
returnankoView(`$$Anko$Factories$CustomViews`.VERTICAL_LAYOUT_FACTORY,theme,init)
}
如第一段所示, init
参数是在_LinearLayout
类型上定义的扩展函数。 在上下文中使用的this
将引用后一种类型的实例。
第二段解释了代表括号内容的内容: init
参数函数。
kotlin dsl