渐进式编程课
KMP 目录
第 21 课2026.08.06

共享 @Composable 函数不会自己创建 Android 窗口或 iOS 控制器。每个平台仍需要一个很薄的原生入口,把共同的 App() 放进平台宿主中。

第 21 课:连接 Android 与 iOS 的 Compose 入口

  • 日期:2026-08-06
  • 课程序号:21
  • 知识点:用平台宿主显示同一个 commonMain Compose 界面

用途

共享 @Composable 函数不会自己创建 Android 窗口或 iOS 控制器。每个平台仍需要一个很薄的原生入口,把共同的 App() 放进平台宿主中。

核心概念

  • commonMain 定义共享 UI 根组件 App()。
  • Android 使用 Activity.setContent {} 承载 Compose。
  • iOS 使用 ComposeUIViewController {} 创建 UIKit 控制器。
  • 平台入口负责窗口、系统生命周期和平台依赖组装。
  • 业务状态和通用界面继续留在共享层,入口不复制页面逻辑。

示例代码

commonMain/App.kt:

kotlin
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable

@Composable
fun App() {
    MaterialTheme {
        Text(text = "Hello Compose Multiplatform")
    }
}

Android 入口 androidMain/MainActivity.kt:

kotlin
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            App()
        }
    }
}

iOS 入口 iosMain/MainViewController.kt:

kotlin
import androidx.compose.ui.window.ComposeUIViewController

fun MainViewController() = ComposeUIViewController {
    App()
}

Xcode 侧使用共享框架导出的 MainViewController() 作为界面控制器。Android 和 iOS 的入口不同,但最终执行的是同一个 App()。

真实项目中,入口还可以从平台级 Composition Root 获取 UserStore 等依赖,再传给共享 App();不要在每次组件重组时重新创建网络客户端或 Repository。

5 分钟练习

给共享 App() 增加 platformName: String 参数,让 Android 显示 "Android",iOS 显示 "iOS"。

参考答案

共享组件:

kotlin
@Composable
fun App(platformName: String) {
    MaterialTheme {
        Text(text = "运行平台:$platformName")
    }
}

Android 入口:

kotlin
setContent {
    App(platformName = "Android")
}

iOS 入口:

kotlin
fun MainViewController() = ComposeUIViewController {
    App(platformName = "iOS")
}

平台值由平台入口提供,共享 UI 只接收并渲染参数。

与上一课的联系

上一课把 StateFlow 接入共享 Compose UI;本课解释这棵共享 UI 树如何真正进入 Android Activity 和 iOS UIViewController。至此,数据链路和两个平台入口已经连通。

参考资料