使用 Kotlin 多平台建置全端應用程式
程式碼範例: full-stack-task-manager
使用的外掛程式:
在本文中,您將學習如何使用 Kotlin 開發一個全端應用程式,它可以在 Android、iOS 和桌面平台運行,同時利用 Ktor 進行無縫資料處理。
完成本教學後,您將了解如何執行以下操作:
- 使用 Kotlin Multiplatform 建立全端應用程式。
- 理解使用 IntelliJ IDEA 產生的專案。
- 建立呼叫 Ktor 服務的 Compose Multiplatform 用戶端。
- 在設計的不同層級之間重複使用共享類型。
- 正確包含和配置多平台函式庫。
在之前的教學中,我們使用任務管理器 (Task Manager) 範例來
您將建立一個針對 Android、iOS 和桌面平台的用戶端,使用 Ktor 服務來 獲取要顯示的資料。在可能的情況下,您將在用戶端和伺服器之間共享資料類型, 加快開發速度並減少潛在錯誤。
先決條件
與之前的文章一樣,您將使用 IntelliJ IDEA 作為 IDE。要安裝和配置您的 環境,請參閱 Kotlin Multiplatform 快速入門 指南。
如果這是您第一次使用 Compose Multiplatform,我們建議您先完成 Compose Multiplatform 入門 教學,再開始本教學。為了降低任務的複雜性,您可以專注於單一用戶端平台。例如,如果您從未使用過 iOS,那麼專注於桌面或 Android 開發可能更明智。
建立新專案
請改用 IntelliJ IDEA 中的 Kotlin Multiplatform 專案精靈,而非 Ktor 專案產生器。 它將建立一個基本的多平台專案,您可以擴展該專案以包含 用戶端和服務。用戶端既可以使用原生 UI 函式庫,例如 SwiftUI,但在本教學中 您將透過使用 Compose Multiplatform 為所有平台建立共享 UI。
- 啟動 IntelliJ IDEA。
- 在 IntelliJ IDEA 中,選擇 File | New | Project 。
- 在左側面板中,選擇 Kotlin Multiplatform 。
- 在 New Project 視窗中指定以下欄位:
- Name : full-stack-task-manager
- Group : com.example.ktor
選擇 Android 、 Desktop 和 Server 作為目標平台。
如果您使用的是 Mac,也請選擇 iOS 。確保已選取 Share UI 選項。
按一下 Create 按鈕,等待 IDE 產生並匯入專案。
執行服務
- 在 Project 視圖中,導覽至 server/src/main/kotlin/com/example/ktor/full_stack_task_manager 並開啟 Application.kt 檔案。
- 按一下 Run 按鈕 (
) 在
main()
函式旁邊以啟動應用程式。Run 工具視窗中將開啟一個新分頁,日誌結尾顯示訊息「Responding at http://0.0.0.0:8080」。
導覽至 http://0.0.0.0:8080/ 以開啟應用程式。 您應該會在瀏覽器中看到 Ktor 顯示的訊息。
檢查專案
server 資料夾是專案中三個 Kotlin 模組之一。另外兩個是 shared 和 composeApp 。
server 模組的結構與 Ktor Project Generator 產生的結構非常相似。 您有一個專用的建置檔案來 宣告外掛程式和相依性,以及一個包含用於建置和啟動 Ktor 服務的程式碼來源集:

如果您查看 Application.kt 檔案中的路由指令,您將看到對 greet()
函式的呼叫:
這會建立一個 Greeting
類型的實例並調用其 greet()
方法。 Greeting
類別定義在 shared 模組中:
shared 模組包含將在不同目標平台中使用的程式碼。
shared 模組集中的 commonMain 來源集保存著將在所有平台中使用的類型。 如您所見,這就是 Greeting
類型定義的地方。 這也是您將放置伺服器和所有不同用戶端平台之間共享的通用程式碼的地方。
shared 模組還包含您希望提供用戶端的每個平台的來源集。這是因為 在 commonMain 中宣告的類型可能需要因目標平台而異的功能。對於 Greeting
類型,您希望使用平台特定 API 獲取當前平台的名稱。 這透過 預期 (expected) 和實際 (actual) 宣告實現。
在 shared 模組的 commonMain 來源集中,您使用 expect
關鍵字宣告 getPlatform()
函式:
然後每個目標平台 必須提供 getPlatform()
函式的 actual
宣告,如下所示:
專案中還有一個額外的模組,即 composeApp 模組。 它包含 Android、iOS、桌面和網頁用戶端應用程式的程式碼。 這些應用程式目前未連結到 Ktor 服務,但它們確實使用了共享的 Greeting
類別。
執行用戶端應用程式
您可以透過執行目標的執行設定來執行用戶端應用程式。要在 iOS 模擬器上運行 應用程式,請按照以下步驟操作:
- 在 IntelliJ IDEA 中,選擇 iosApp 執行設定和一個模擬裝置。
- 按一下 Run 按鈕 (
) 來執行設定。
當您執行 iOS 應用程式時,它會在幕後使用 Xcode 建置,並在 iOS 模擬器中啟動。 應用程式會顯示一個按鈕,點擊時會切換圖片。
首次按下按鈕時,會將當前平台的詳細資訊新增到其文字中。實現此目的的程式碼位於 composeApp/src/commonMain/kotlin/com/example/ktor/full_stack_task_manager/App.kt :
kotlin這是一個可組合函式,您將在本文稍後修改它。目前重要的是它會顯示一個 UI,並使用共享的
Greeting
類型,而Greeting
類型又使用了實現通用Platform
介面的平台特定類別。
現在您已了解生成專案的結構,您可以逐步新增任務 管理員功能。
新增模型類型
首先,新增模型類型並確保用戶端和伺服器都可以存取它們。
- 導覽至 shared/src/commonMain/kotlin/com/example/ktor/full_stack_task_manager 並建立一個名為 model 的新套件。
- 在新套件內,建立一個名為 Task.kt 的新檔案。
新增一個
enum
來表示優先級,以及一個class
來表示任務。Task
類別使用kotlinx.serialization
函式庫中的Serializable
類型進行註解:kotlin您會注意到匯入和註解都無法編譯。這是因為專案尚未 對
kotlinx.serialization
函式庫有相依性。導覽至 shared/build.gradle.kts 並新增序列化外掛程式:
kotlin在同一個檔案中,為 commonMain 來源集新增一個相依性:
kotlin- 導覽至 gradle/libs.versions.toml 並定義以下內容: toml
- 在 IntelliJ IDEA 中,選擇 Build | Sync Project with Gradle Files 以套用更新。一旦 Gradle 匯入完成,您應該會發現您的 Task.kt 檔案成功編譯。
請注意,如果沒有包含序列化外掛程式,程式碼也能夠編譯,然而, 透過網路序列化 Task
物件所需的類型將不會產生。這會導致在嘗試調用服務時出現執行時期錯誤。
將序列化外掛程式放置在另一個模組(例如 server 或 composeApp )不會在建置時期造成錯誤。但同樣地,序列化所需的額外類型將不會產生,導致執行時期錯誤。
建立伺服器
下一個階段是為我們的任務管理器建立伺服器實作。
- 導覽至 server/src/main/kotlin/com/example/ktor/full_stack_task_manager 資料夾並建立一個名為 model 的子套件。
在此套件內,建立一個新的 TaskRepository.kt 檔案並為我們的儲存庫新增以下介面:
kotlin在同一個套件中,建立一個名為 InMemoryTaskRepository.kt 的新檔案,其中包含以下類別:
kotlin導覽至 server/src/main/kotlin/.../Application.kt 並將現有程式碼替換為以下實作:
kotlin此實作與之前的教學非常相似,不同之處在於,為了簡化起見,現在您已將所有路由程式碼放置在
Application.module()
函式中。輸入此程式碼並新增匯入後,您將發現多個編譯器錯誤,因為程式碼使用了多個需要包含為相依性的 Ktor 外掛程式, 包括用於與網頁用戶端互動的
CORS外掛程式。所需相依性:io.ktor:%artifact_name% 程式碼範例:full-stack-task-manager 原生伺服器支援:✅- 開啟 gradle/libs.versions.toml 檔案並定義以下函式庫: toml
開啟伺服器模組建置檔案 ( server/build.gradle.kts ) 並新增以下相依性:
kotlin- 再次從主功能表選擇 Build | Sync Project with Gradle Files。 匯入完成後,您應該會發現
ContentNegotiation
類型和json()
函式的匯入正常運作。 - 重新執行伺服器。您應該會發現可以從瀏覽器存取路由。
建立用戶端
為了讓您的用戶端能夠存取伺服器,您需要包含 Ktor Client。這涉及到三種類型的相依性:
- Ktor Client 的核心功能。
- 用於處理網路連線的平台特定引擎。
- 內容協商和序列化的支援。
- 在 gradle/libs.versions.toml 檔案中,新增以下函式庫: toml
- 導覽至 composeApp/build.gradle.kts 並新增以下相依性: kotlin
完成此操作後,您可以為用戶端新增一個
TaskApi
類型,作為 Ktor Client 的輕量封裝。 - 從主功能表選擇 Build | Sync Project with Gradle Files 以匯入建置檔案中的變更。
- 導覽至 composeApp/src/commonMain/kotlin/com/example/ktor/full_stack_task_manager 並建立一個名為 network 的新套件。
在新套件內,為用戶端配置建立一個新的 HttpClientManager.kt :
kotlin請注意,您應該將
1.2.3.4
替換為您當前機器的 IP 位址。您將 無法從 Android 虛擬裝置或 iOS 模擬器上運行的程式碼向0.0.0.0
或localhost
發出呼叫。在相同的 composeApp/.../full_stack_task_manager/network 套件中,建立一個新的 TaskApi.kt 檔案,並加入以下實作:
kotlin導覽至 commonMain/.../App.kt 並將現有的 App 可組合函式替換為以下實作。 這將使用
TaskApi
類型從伺服器檢索任務列表,然後 在欄位中顯示每個任務的名稱:kotlin在伺服器運行時,透過執行 iosApp 執行設定來測試 iOS 應用程式。
按一下 Fetch Tasks 按鈕以顯示任務列表:
NOTE
在此示範中,我們為求清晰而簡化了流程。在實際應用中,避免透過網路傳送未加密的資料至關重要。在 Android 平台上,您需要明確授予應用程式網路權限並 允許它以明文形式傳送和接收資料。要啟用這些權限,請開啟 composeApp/src/androidMain/AndroidManifest.xml 並新增以下設定:
xml使用 composeApp 執行設定來執行 Android 應用程式。 您現在應該會發現您的 Android 用戶端也能運行:
對於桌面用戶端,您應該為包含視窗指定尺寸和標題。 開啟 composeApp/src/desktopMain/.../main.kt 檔案並透過更改
title
和設定state
屬性來修改程式碼:kotlin使用 composeApp [desktop] 執行設定來執行桌面應用程式:
使用 composeApp [wasmJs] 執行設定來執行網頁用戶端:
改進使用者介面 (UI)
用戶端現在正在與伺服器通訊,但這很難說是一個美觀的 UI。
開啟位於 composeApp/src/commonMain/.../full_stack_task_manager 中的 App.kt 檔案,並將現有的
App
替換為以下的App
和TaskCard
可組合函式:kotlin透過此實作,您的用戶端現在擁有了一些基本功能。
透過使用
LaunchedEffect
類型,所有任務在啟動時載入,而LazyColumn
可組合函式允許使用者捲動瀏覽任務。最後,建立了一個單獨的
TaskCard
可組合函式,它又使用一個Card
來顯示每個Task
的詳細資訊。已經新增了按鈕以 刪除和更新任務。重新執行用戶端應用程式 — 例如 Android 應用程式。 您現在可以捲動瀏覽任務、查看其詳細資訊並刪除它們:
新增更新功能
為了完善用戶端,請整合允許更新任務詳細資訊的功能。
- 導覽至 composeApp/src/commonMain/.../full_stack_task_manager 中的 App.kt 檔案。
新增
UpdateTaskDialog
可組合函式和必要的匯入,如下所示:kotlin這是一個可組合函式,它透過對話框顯示
Task
的詳細資訊。description
和priority
放置在TextField
可組合函式中,以便可以 更新。當使用者按下更新按鈕時,它會觸發onConfirm()
回呼。更新同一個檔案中的
App
可組合函式:kotlin您正在儲存額外的狀態部分,即選定的當前任務。如果此值不為 null, 那麼我們調用我們的
UpdateTaskDialog
可組合函式,並將onConfirm()
回呼設定為使用TaskApi
向伺服器發送 POST 請求。最後,當您建立
TaskCard
可組合函式時,您使用onUpdate()
回呼來設定currentTask
狀態變數。- 重新執行用戶端應用程式。您現在應該能夠使用按鈕更新每個任務的詳細資訊。
後續步驟
在本文中,您已在 Kotlin Multiplatform 應用程式的上下文中使用 Ktor。您現在可以 建立一個包含多個服務和用戶端,針對各種不同平台的專案。
如您所見,在沒有任何程式碼重複或冗餘的情況下建置功能是可能的。 專案所有層所需的類型可以放置在 shared 多平台模組中。 服務才需要的功能放在 server 模組中,而用戶端才需要的功能則放在 composeApp 中。
這種開發不可避免地需要同時具備用戶端和伺服器技術的知識。但您可以使用 Kotlin Multiplatform 函式庫和 Compose Multiplatform 來最大程度地減少您需要學習的新內容。即使您最初 只專注於單一平台,隨著您的應用程式需求增長,您也可以輕鬆新增其他平台。