建立跨平台行動應用程式
Ktor HTTP 客戶端可用於多平台專案。在本教程中,我們將建立一個簡單的 Kotlin Multiplatform Mobile 應用程式,它會發送請求並以純 HTML 文字形式接收響應主體。
若要了解如何建立您的第一個 Kotlin Multiplatform Mobile 應用程式,請參閱 建立您的第一個跨平台行動應用程式。
前置條件
首先,您需要透過在合適的作業系統上安裝必要工具,來設定跨平台行動開發環境。請參閱 設定環境 部分,了解如何執行此操作。
您將需要一台搭載 macOS 的 Mac 以完成本教程中的某些步驟,其中包括編寫 iOS 特有程式碼和執行 iOS 應用程式。
建立新專案
若要啟動新的 Kotlin Multiplatform 專案,有兩種方法可用:
- 您可以在 Android Studio 中從範本建立專案。
- 另外,您可以使用 Kotlin Multiplatform Wizard 來產生一個新專案。該 Wizard 提供了自訂專案設定的選項,例如允許您排除 Android 支援或包含 Ktor Server。
為了本教程的目的,我們將示範從範本建立專案的過程:
- 在 Android Studio 中,選擇 File | New | New Project。
- 在專案範本清單中選擇 Kotlin Multiplatform App,然後點擊 Next。
- 指定應用程式的名稱,然後點擊 Next。在本教程中,應用程式名稱為
KmmKtor
。 - 在下一頁上,保留預設設定並點擊 Finish 建立新專案。 現在,請等待您的專案設定完成。首次執行此操作時,下載和設定所需組件可能需要一些時間。
若要檢視所產生的多平台專案的完整結構,請在 Project view 中從 Android 切換到 Project。
配置建構指令碼
更新 Kotlin Gradle 外掛程式
開啟 gradle/libs.versions.toml
檔案並將 Kotlin 版本更新為最新版本:
kotlin = "2.1.20"
undefined
新增 Ktor 依賴項
若要在您的專案中使用 Ktor HTTP 客戶端,您至少需要新增兩個依賴項:一個客戶端依賴項和一個引擎依賴項。
在 gradle/libs.versions.toml
檔案中新增 Ktor 版本:
[versions]
ktor = "3.2.3"
若要使用 Ktor 的 EAP 版本,您需要新增一個 Space 軟體倉庫。
然後,定義 Ktor 客戶端和引擎函式庫:
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" }
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
若要新增依賴項,請開啟 shared/build.gradle.kts
檔案並按照以下步驟操作:
要在通用程式碼中使用 Ktor 客戶端,請將
ktor-client-core
依賴項新增到commonMain
源集 (source set):kotlinsourceSets { commonMain.dependencies { implementation(libs.ktor.client.core) } }
為每個所需平台將 引擎依賴項 新增到對應的源集:
對於 Android,將
ktor-client-okhttp
依賴項新增到androidMain
源集:kotlinandroidMain.dependencies { implementation(libs.ktor.client.okhttp) }
對於 Android,您也可以使用 其他引擎類型。
對於 iOS,將
ktor-client-darwin
依賴項新增到iosMain
:kotliniosMain.dependencies { implementation(libs.ktor.client.darwin) }
新增協程
要在 Android 程式碼 中使用協程,您需要將 kotlinx.coroutines
新增到您的專案:
開啟
gradle/libs.versions.toml
檔案並指定協程版本和函式庫:kotlin[versions] coroutines = "1.9.0" [libraries] kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "coroutines" }
開啟
build.gradle.kts
檔案並將kotlinx-coroutines-core
依賴項新增到commonMain
源集:kotlinsourceSets { commonMain.dependencies { implementation(libs.ktor.client.core) implementation(libs.kotlinx.coroutines.core) } }
然後,開啟
androidApp/build.gradle.kts
並新增kotlinx-coroutines-android
依賴項:
implementation(libs.compose.ui)
}
點擊 gradle.properties
檔案右上角的 Sync Now 以安裝新增的依賴項。
更新您的應用程式
共享程式碼
若要更新 Android 和 iOS 之間共享的程式碼,請開啟 shared/src/commonMain/kotlin/com/example/kmmktor/Greeting.kt
檔案並將以下程式碼新增到 Greeting
類別中:
package com.example.kmmktor
import io.ktor.client.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
class Greeting {
private val client = HttpClient()
suspend fun greeting(): String {
val response = client.get("https://ktor.io/docs/")
return response.bodyAsText()
}
}
Android 程式碼
若要從 Android 程式碼呼叫掛起函式 greeting
,我們將使用 rememberCoroutineScope
。
開啟 androidApp/src/main/java/com/example/kmmktor/android/MainActivity.kt
檔案並按如下方式更新 MainActivity
程式碼:
package com.example.kmmktor.android
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.example.kmmktor.Greeting
import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApplicationTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
val scope = rememberCoroutineScope()
var text by remember { mutableStateOf("Loading") }
LaunchedEffect(true) {
scope.launch {
text = try {
Greeting().greeting()
} catch (e: Exception) {
e.localizedMessage ?: "error"
}
}
}
GreetingView(text)
}
}
}
}
}
@Composable
fun GreetingView(text: String) {
Text(text = text)
}
@Preview
@Composable
fun DefaultPreview() {
MyApplicationTheme {
GreetingView("Hello, Android!")
}
}
在建立的作用域內,我們可以呼叫共享的 greeting
函式並處理可能的異常。
iOS 程式碼
開啟
iosApp/iosApp/iOSApp.swift
檔案並更新應用程式的入口點:Swiftimport SwiftUI @main struct iOSApp: App { var body: some Scene { WindowGroup { ContentView(viewModel: ContentView.ViewModel()) } } }
開啟
iosApp/iosApp/ContentView.swift
檔案並按如下方式更新ContentView
程式碼:Swiftimport SwiftUI import shared struct ContentView: View { @ObservedObject private(set) var viewModel: ViewModel var body: some View { Text(viewModel.text) } } extension ContentView { class ViewModel: ObservableObject { @Published var text = "Loading..." init() { Greeting().greeting { greeting, error in DispatchQueue.main.async { if let greeting = greeting { self.text = greeting } else { self.text = error?.localizedDescription ?? "error" } } } } } }
在 iOS 上,掛起函式
greeting
可作為帶有回呼函式的函式使用。
在 Android 上啟用網路存取
我們需要做的最後一件事是為 Android 應用程式啟用網路存取。 開啟 androidApp/src/main/AndroidManifest.xml
檔案並使用 uses-permission
元素啟用所需的權限:
<manifest>
<uses-permission android:name="android.permission.INTERNET" />
<application>
...
</application>
</manifest>
執行您的應用程式
若要在 Android 或 iOS 模擬器上執行所建立的多平台應用程式,請選擇 androidApp 或 iosApp 並點擊 Run。 模擬器應該將接收到的 HTML 文件顯示為純文字。