在建立全新的 Compose for Desktop 專案後,我們只知道怎麼運行專案及預覽元件,對於應用程式組成及程式碼細節並不清楚。因此今天的耕讀筆記就要來閱讀由 IntelliJ IDEA 幫我們建立的 Compose 程式碼,並拆解幾個基本的應用程式元件。
main()
函式有 Kotlin 開發經驗的讀者都知道,Kotlin 支援 Top-Level Function 的語法設計,只要在 Kotlin 檔案裡宣告 main()
函式,該函式就可以成為應用程式的進入點。在我們新建立的 Compose for Desktop 專案裡,應用程式的進入點就在 src/jvmMain/kotlin/Main.kt
檔案裡的第 29 行:
fun main() = application {
}
由於 Kotlin 函式支援 Expression Body 語法,也就是說,當一個函式的內容只做一個動作且回傳,則可以省略函式頭尾的大括號({}
),以等於(=
)接上函式內容。因此專案裡的 main()
函式直接以等於符號接上 application()
函式。由 Jetpack Compose 宣告的 application()
函式在這邊可以建立一個 Compose 應用程式,而因為運行在 Desktop 平台上,所以就會變成一個桌面應用程式。
在 application()
函式裡呼叫了 Window()
函式,若追溯其源碼會發現,Window()
是一個 Compose 元件,可以在桌面上產生一個視窗。我們可以將視窗設定以參數的方式傳遞給 Window()
函式,以專案內建的範例程式碼為例,可以指定當視窗被關閉時(onCloseRequest)要做的動作(exitApplication)。
Window(onCloseRequest = ::exitApplication) {
App()
}
Compose 元件是以樹狀階層的方式宣告建立的,我們可以看到在 Window()
函式裡,呼叫了另一個 App()
函式。在 IDE 裡點一下 App()
函式,會發現它並不是 Jetpack Compose 內建的元件,而是宣告在 17 行的自訂函式。
@Composable
@Preview
fun App() {
}
從 App()
函式的宣告方式,就可以發現 Compose 元件在撰寫時的幾個慣例:
@Composable
Annotation,Kotlin Compiler Plugin 才會將其編譯為 Compose 元件。@Preview
Annotation,IDE 會在函式旁邊加上 Compose Icon,點選就能在右邊的工具窗口預覽。也可以另外宣告一個專門用於預覽的函式,命名慣例採 元件名稱+Prevew
(AppPreview()
),可在預覽函式裡傳入不同的參數,預覽不同設定值對元件樣式的影響。var text by remember { mutableStateOf("Hello, World!") }
MaterialTheme {
Button(onClick = {
text = "Hello, Desktop!"
}) {
Text(text)
}
}
在 App()
元件裡,可看到分為兩個部份的程式,上半部 text
變數的功能在於儲存要顯示在畫面上的字串,這部份牽涉到 Compose 的狀態管理,我們先暫且跳過,本系列的後半部會再針對這塊做較深入的研究。而下半部的程式碼可以看出以階層式的方式,宣告一個使用 Material 樣式的 Button()
(按鈕),按鈕上顯示一段 Text()
(文字)。
在按鈕的設定裡,傳入一個 Closure 做為按鈕點擊事件(onClick()
)的 Handler,在 Handler 裡面可以看到其行為是修改 text
變數的內容,而不是直接更改 Text()
元件的設定。由此可見,Compose 的核心思想,是透過更改狀態,讓 UI 自行依照監聽的狀態值來重繪其外觀,也是 Declarative UI 很重要的特性。
在今天的筆記裡,我們快速地看完 Compose for Desktop 專案裡的核心程式碼,了解應用程式如何啟動、如何以 Compose 元件階層式的建構應用程式畫面、Compose 元件的實作慣例、Declarative UI 在狀態管理及繪製畫面的特性…等。
由此可知,要熟悉 Compose,得先了解其內建元件有哪些及其使用方式。接下來,筆者將分幾不同的類別,綜覽各 Compose 元件。