溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Kotlin 基礎(chǔ)(二)- DSL

發(fā)布時間:2020-07-19 16:16:06 來源:網(wǎng)絡(luò) 閱讀:399 作者:Android丶VG 欄目:移動開發(fā)

所謂 DSL 領(lǐng)域?qū)S谜Z言(Domain Specified Language/ DSL),其基本思想是“求專不求全”,不像通用目的語言那樣目標(biāo)范圍涵蓋一切軟件問題,而是專門針對某一特定問題的計算機(jī)語言。

Kotlin 基礎(chǔ)(二)- DSL

Kotlin DSL 定義:使用 Kotlin 語言開發(fā)的,解決特定領(lǐng)域問題,具備獨(dú)特代碼結(jié)構(gòu)的 API 。

一、DSL

DSL(domain specific language),即領(lǐng)域?qū)S谜Z言:專門解決某一特定問題的計算機(jī)語言,比如大家耳熟能詳?shù)?SQL 和正則表達(dá)式。使用DSL的編程風(fēng)格,可以讓程序更加簡單干凈、直觀簡潔。當(dāng)然,我們也可以創(chuàng)建自己的 DSL。相對于傳統(tǒng)的 API, DSL 更加富有表現(xiàn)力、更符合人類語言習(xí)慣。

如果為解決某一特定領(lǐng)域問題就創(chuàng)建一套獨(dú)立的語言,開發(fā)成本和學(xué)習(xí)成本都很高,因此便有了內(nèi)部 DSL 的概念。所謂內(nèi)部 DSL,便是使用通用編程語言來構(gòu)建 DSL,比如,Kotlin DSL。

1.1 常見的 DSL

常見的 DSL 在很多領(lǐng)域都能看到,例如:

  • 軟件構(gòu)建領(lǐng)域 Ant
  • UI 設(shè)計師 HTML
  • 硬件設(shè)計師 VHDL
1.2 通用編程語言 vs DSL

通用編程語言(如 Java、Kotlin、Android等),往往提供了全面的庫來幫助開發(fā)者開發(fā)完整的應(yīng)用程序,而 DSL 只專注于某個領(lǐng)域,比如 SQL 僅支持?jǐn)?shù)據(jù)庫的相關(guān)處理,而正則表達(dá)式只用來檢索和替換文本,我們無法用 SQL 或者正則表達(dá)式來開發(fā)一個完整的應(yīng)用。

  • DSL 供非程序員使用,供領(lǐng)域?qū)<沂褂茫?/li>
  • DSL 有更高級的抽象,不涉及類似數(shù)據(jù)結(jié)構(gòu)的細(xì)節(jié);
  • DSL 表現(xiàn)力有限,其只能描述該領(lǐng)域的模型,而通用編程語言能夠描述任意的模型;

無論是通用編程語言,還是領(lǐng)域?qū)S谜Z言,最終都是要通過 API 的形式向開發(fā)者呈現(xiàn)。良好的、優(yōu)雅的、整潔的、一致的 API 風(fēng)格是每個優(yōu)秀開發(fā)者的追求,而 DSL 往往具備獨(dú)特的代碼結(jié)構(gòu)和一致的代碼風(fēng)格。

二、Kotlin DSL 在 Android 開發(fā)的應(yīng)用

2.1 Anko

Anko 是一個 DSL (Domain-Specific Language), 它是 JetBrains 出品的,用 Kotlin 開發(fā)的安卓框架。它主要的目的是用來替代以前 XML 的方式來使用代碼生成 UI 布局。

2.1.1 使用

Anko 中, 不需要繼承其他奇怪的類,只要標(biāo)準(zhǔn)的 Activity, Fragment,F(xiàn)ragmentActivity 或者其他任意的類

首先, 在使用 Anko 的 DSL 的類中導(dǎo)入 org.jetbrains.anko.* .

DSL 可以在 onCreate()中使用:

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

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

不需要顯示的調(diào)用 setContentView(R.layout.something), Anko 自動為 Activity(只會對Activity)進(jìn)行 set content view

padding, hint 和 textSize 是 擴(kuò)展屬性. 大多數(shù) View 具有這些屬性,允許使用 text = “Some text” 代替 setText(“Some text”).

verticalLayout (一個豎直方向的 LinearLayout), editText 和 button

擴(kuò)展函數(shù). 這些函數(shù)存在與ANdroid 框架中的大部View中, Activities, Fragments ( android.support 包中的) 甚至 Context同樣適用.

如果有一個 Context 實(shí)例, 可以寫出下面的DSL結(jié)構(gòu):

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

變量 name 成為了 EditText類型.

2.1.2 Helper 方法

你可能注意到了,前面 button 方法接了一個字符串參數(shù),這樣的Helper方法同樣使用與 TextView, EditText, Button , ImageView.

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

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

在父布局中布局控件可能需要使用 LayoutParams.xml 中長這樣:

<ImageView 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android_layout_marginLeft="5dip"
    android_layout_marginTop="10dip"
    android:src="@drawable/something" />

Anko 中, 在 View 的后面使用 lparams 來實(shí)現(xiàn)類似與 xml 的 LayoutParams。

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

如果指定了 lparams,但是沒有指定 width 或者 height, 默認(rèn)是 WRAP_CONTENT,但是你可以自己通過使用 named arguments指定.

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

  • horizontalMargin 同時設(shè)置 left 和 right margins
  • verticalMargin 同時設(shè)置 top 和 bottom
  • margin 同時設(shè)置4個方向的 margins
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent">

    <EditText
        android:id="@+id/todo_title"
        android:layout_width="match_parent"
        android:layout_heigh="wrap_content"
        android:hint="@string/title_hint" />

    <!-- Cannot directly add an inline click listener as onClick delegates implementation to the activity -->
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/add_todo" />

</LinearLayout>

使用 Anko 之后,可以用代碼實(shí)現(xiàn)布局,并且 button 還綁定了點(diǎn)擊事件。

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 的一個主要優(yōu)點(diǎn)在于,它需要很少的時間即可理解和傳達(dá)某個領(lǐng)域的詳細(xì)信息。

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" 
     } 
 } 

關(guān)于我
更多信息可以點(diǎn)擊+關(guān)于我 , 非常希望和大家一起交流 , 共同進(jìn)步

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI