Kotlin学习笔记——(十)用高阶函数、扩展函数简单模仿声明式UI

注:编码工具为IntelliJ

目录

案例一:

案例二:

案例三:


案例一:

package step_ten

fun main() {
    // 看到花括号,想到lambda,
    layout {
        // 看到lambda里面的花括号,想到类的成员函数时高阶函数,省略了this.
        textview {
            println("textview")
        }

        button {
            println("button")
        }
    }
}

private class Helper

// 可以用扩展函数,也可以定义在类的内部
private inline fun Helper.textview(lambda: () -> Unit) = lambda()
private inline fun Helper.button(lambda: () -> Unit) = lambda()
private inline fun layout(
    // 因为要在lambda里面调用类的高阶函数,要用到this,所以要声明成匿名扩展函数
    lambda: Helper.() -> Unit
):
        Helper {
    val helper = Helper()
    helper.lambda()
    return helper
}

输出:

textview
button

案例二:

package step_ten

fun main() {
    // 看到花括号,想到lambda
    manifest {
        // 看到lambda里调用函数,想到类的函数是普通函数,省略了this.
        pkg("com.test")
        permission("android.permission.INTERNET")
        // 看到lambda里调用lambda,想到类的函数是高阶函数,省略了this.
        application {
            // 看到lambda里调用lambda,想到类的函数是高阶函数,省略了this.
            activity {
                intent_filter {
                    action("android.intent.action.MAIN")
                    category("android.intent.category.LAUNCHER")
                }
            }
            service {
                intent_filter {

                }
            }
            receiver {
                intent_filter {

                }
            }
            provider {
                intent_filter {

                }
            }
        }
    }
}

private class IntentFilter{
    fun action(s: String) = println("action is $s")
    fun category(s: String) = println("category is $s")
}

private class Component{
    inline fun intent_filter(lambda: IntentFilter.() -> Unit): IntentFilter{
        val intentFilter = IntentFilter()
        intentFilter.lambda()
        return intentFilter
    }
}

private class Application{
    inline fun activity(lambda: Component.() -> Unit): Component{
        val component = Component()
        component.lambda()
        return component
    }

    inline fun service(lambda: Component.() -> Unit): Component{
        val component = Component()
        component.lambda()
        return component
    }

    inline fun receiver(lambda: Component.() -> Unit): Component{
        val component = Component()
        component.lambda()
        return component
    }

    inline fun provider(lambda: Component.() -> Unit): Component{
        val component = Component()
        component.lambda()
        return component
    }
}

private class Manifest {
    fun pkg(s: String) = println("package is $s")
    fun permission(s: String) = println("permission is $s")

    inline fun application(lambda: Application.() -> Unit): Application{
        val application = Application()
        application.lambda()
        return application
    }
}

private inline fun manifest(
    // 因为要在lambda里面调用类的高阶函数,要用到this,所以要声明成匿名扩展函数
    lambda: Manifest.() -> Unit
): Manifest {
    val manifest = Manifest()
    lambda(manifest)
    return manifest
}

输出:

package is com.test
permission is android.permission.INTERNET
action is android.intent.action.MAIN
category is android.intent.category.LAUNCHER

案例三:

package step_ten

import java.io.File

fun main() {
    val list = listOf("30", "70", "1000")
    val htmlObj = html {
        head {
            title { +"Html自动生成" }
        }
        body {
            h1 { +"一行白鹭上青天" }
            p { +"门泊东吴万里船" }
            a(href = "https://www.google.com") { +"google" }
            p {
                +"牛奶面包"
                b { +"outdoor" }
                +"3366"
                a(href = "https://404") { +"no way" }
                +"breakfast"
            }
            p { +"a little scheme" }
            p {
                +"时光如流水"
                ul {
                    for (item in list)
                        li {
                            +item
                        }
                }
            }
        }
    }
    val file = File("auto.html")
    val htmlText = htmlObj.toString()
    file.writeText(htmlText)
    println(htmlText)
}

private inline fun html(lambda: Html.() -> Unit): Html {
    val html = Html()
    html.lambda()
    return html
}

private class Html : TagClass("html") {
    inline fun head(lambda: Head.() -> Unit) {
        val head = Head()
        head.lambda()
        subElements += head
    }

    inline fun body(lambda: Body.() -> Unit) {
        val body = Body()
        body.lambda()
        subElements += body
    }
}

private class Head : TagClass("head") {
    inline fun title(lambda: Title.() -> Unit) {
        val title = Title()
        title.lambda()
        subElements += title
    }
}

private class Title : TagClass("title")


private open class Body(tagName: String = "body"): TagClass(tagName){
    inline fun h1(lambda: H1.() -> Unit){
        val h1 = H1()
        h1.lambda()
        subElements += h1
    }

    inline fun p(lambda: P.() -> Unit){
        val p = P()
        p.lambda()
        subElements += p
    }

    inline fun a(href: String, lambda: A.() -> Unit){
        val a = A()
        a.lambda()
        subElements += a
        a.href = href
    }

    inline fun b(lambda: B.() -> Unit){
        val b = B()
        b.lambda()
        subElements += b
    }

    inline fun ul(lambda: UL.() -> Unit){
        val ul = UL()
        ul.lambda()
        subElements += ul
    }

    inline fun li(lambda: LI.() -> Unit){
        val li = LI()
        li.lambda()
        subElements += li
    }
}

private class H1: Body("h1")
private class P: Body("p")
private class A: Body("a"){
    var href: String
        get() = attributes["href"]!!
        set(value){
            attributes["href"] = value
        }
}
private class B: Body("b")
private class UL: Body("ul")
private class LI: Body("li")

// HTML元素抽象 文本 标签
private interface Element {
    fun transform(builder: StringBuilder, indent: String)
}

private class TextElement(val text: String) : Element {
    override fun transform(builder: StringBuilder, indent: String) {
        builder.append("$indent$text\n")
    }
}

private open class Tag(val tagName: String) : Element {
    val subElements = arrayListOf<Element>()
    val attributes = hashMapOf<String, String>()
    override fun transform(builder: StringBuilder, indent: String) {
        builder.append("$indent<$tagName")
        handleAttributes(builder)
        for(e in subElements){
            e.transform(builder, "$indent ")
        }
        builder.append("$indent</$tagName>\n")
    }

    fun handleAttributes(builder: StringBuilder){
        for ((k, v) in attributes) {
            builder.append(" $k=\"$v\"")
        }
        builder.append(">\n")
    }

    override fun toString(): String {
        val builder = StringBuilder()
        transform(builder, "")
        return builder.toString()
    }
}

private open class TagClass(tagName: String) : Tag(tagName) {
    operator fun String.unaryPlus() {
        subElements += TextElement(this)
    }
}

输出:

<html>
 <head>
  <title>
   Html自动生成
  </title>
 </head>
 <body>
  <h1>
   一行白鹭上青天
  </h1>
  <p>
   门泊东吴万里船
  </p>
  <a href="https://www.google.com">
   google
  </a>
  <p>
   牛奶面包
   <b>
    outdoor
   </b>
   3366
   <a href="https://404">
    no way
   </a>
   breakfast
  </p>
  <p>
   a little scheme
  </p>
  <p>
   时光如流水
   <ul>
    <li>
     30
    </li>
    <li>
     70
    </li>
    <li>
     1000
    </li>
   </ul>
  </p>
 </body>
</html>

上一篇:kotlin与java在Android开发中的简单对比(正在更新中),快手android面试经验


下一篇:Servicenow - 更改列表默认每页显示记录数(Change List Default Row-Count PerPage)