前言

前面1‑19课学习的是Android平台原生Jetpack Compose,只能运行在安卓手机。
Compose‑Multiplatform(C‑MP)基于KMP(Kotlin Multiplatform),同一套Compose UI代码,可以编译运行Android、Windows/macOS/Linux桌面,iOS(尚处于逐步完善)。
本节课区分原生Jetpack‑Compose 和 Compose‑Multiplatform;基础工程结构;共享模块;简单HelloWorld。

知识点清单

  1. Jetpack Compose(Android专属) vs Compose‑Multiplatform(KMP跨平台)
  2. KMP工程结构:shared共享模块 + 各平台独立模块(android、desktop)
  3. expect‑actual 声明‑实际,用来处理平台特定代码
  4. 共享模块编写跨平台UI;桌面入口main函数;Android的Activity入口
  5. 简单HelloWorld示例

环境前置
IDE:Android Studio(安装KMP插件);JDK17;Gradle版本尽量新。

完整示例源码

  
/**
 * shared 共享模块‑跨平台UI代码(android、desktop都复用这部分)
 */
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier

@Composable
fun SharedMainScreen() {
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(text = "Compose‑Multiplatform 跨平台演示!")
        Button(onClick = {}) {
            Text("通用按钮")
        }
    }
}

/**
 * desktop桌面端入口,独立main函数,没有Activity
 */
fun main() {
    androidx.compose.ui.window.application {
        androidx.compose.ui.window.Window(onCloseRequest = ::exitApplication) {
            SharedMainScreen()
        }
    }
}

/**
 * Android端入口 Activity(android模块)
 */
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent

class AndroidMainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            SharedMainScreen()
        }
    }
}

/**
 * expect‑actual平台差异化代码示例
 */
expect fun getPlatformName(): String

//android实现(android源集)
actual fun getPlatformName(): String {
    return "Android"
}

//desktop实现(desktop源集)
actual fun getPlatformName(): String {
    return "Desktop"
}
 

逐行解读

  1. Jetpack‑Compose VS Compose‑Multiplatform
  • Jetpack Compose:Android专属,只能跑安卓手机;依赖Android Framework;API由Google Android团队维护。
  • Compose‑Multiplatform:KMP跨平台;UI渲染层独立;一套Compose声明式UI;编译输出Android App、桌面exe/dmg;iOS还在持续完善;

⚠️注意:不是写一次就所有平台完全适配!依然会存在平台差异,平台特定逻辑需要expect‑actual。

  1. 工程模块结构
  • shared :共享模块,存放大部分Compose UI、业务逻辑;这部分代码会被Android模块和Desktop模块同时引用;
  • androidApp :安卓应用模块;只保留Activity,直接复用shared里面的@Composable页面;
  • desktopApp :桌面应用模块;入口是普通fun main(),没有Activity,没有Android生命周期;使用Window创建应用窗口。
  1. expect‑actual(声明‑实际)
    当业务需要调用平台独有的能力:比如读取Android权限;Windows读取本地文件;iOS通知;
    先在shared的common源集写 expect fun xxx() 做抽象声明;
    然后分别在android、desktop源集编写 actual fun xxx() 提供对应平台的实现。
    common共享代码就可以调用这个函数;编译期会自动链接对应平台的实现。

expect‑actual是KMP解决平台差异化的核心机制。

  1. 桌面端入口 application{}与Window{}
    桌面端没有Activity; application {} 代表整个桌面应用程序; Window{} 代表一个窗口;可以打开多个窗口; exitApplication() 关闭整个程序。
  2. 资源处理痛点
    图片、字符串资源:C‑MP现在有统一资源方案;旧项目经常需要分别维护各平台资源;新项目优先使用新版gradle的KMP资源管理。

容易踩坑

  1. ❌误以为KMP写一套代码之后所有平台不用做任何适配;UI控件行为、系统权限、文件路径各个平台都不一样;平台相关逻辑仍然要用expect‑actual隔离。
  2. ❌ 在common共享代码里面直接调用Android SDK(Context、Toast);common源集看不到Android框架API,编译报错;必须抽象之后交给平台层actual实现。
  3. ❌ 直接把原生Android Jetpack Compose项目简单改一改就当成C‑MP;工程需要重新搭建KMP模块结构。
  4. ❌ 桌面端照搬Android的Activity生命周期;桌面没有Activity,窗口生命周期自己管理。
  5. ✅ shared模块放通用UI;androidApp、desktopApp作为外壳;expect‑actual隔离平台独有逻辑;桌面入口main+application+Window。

多元化习题(练习)

习题1【基础‑改错题】

直接在KMP的common共享代码里面调用Android的Toast,为什么编译报错?
答案:
common共享源集不依赖Android SDK;看不到Android平台API;不能直接调用;需要用expect声明接口,Android模块使用actual完成平台实现。
解读:
共享层只写跨平台通用逻辑;平台能力通过expect‑actual向外抽象。

习题2【基础‑代码修改题】

common里面声明一个获取操作系统版本名称的expect函数(只写expect声明)
答案:

  
expect fun getOsVersionName(): String
 

解读:
之后分别在android、desktop源集编写actual实现。

习题3【进阶‑补充代码题】

desktop端Compose‑Multiplatform如何关闭整个桌面应用?
答案:
调用 exitApplication() ;该函数需要放在application作用域内;一般写在窗口关闭回调onCloseRequest。
解读:
桌面没有finish();使用exitApplication退出进程。

习题4【综合‑逻辑应用题】

KMP Compose‑Multiplatform项目为什么要拆分成shared共享模块 + androidApp、desktopApp外壳模块?
答案:
UI与业务尽量全部放在shared,实现最大程度复用;androidApp与desktopApp仅仅作为各平台薄薄的外壳,负责提供平台入口、平台特定实现;后续新增iOS目标时,只需要新增一层外壳模块,尽量不用修改shared业务代码。
解读:
分离通用业务与平台外壳是KMP工程的核心思想。

习题5【概念简答题】

Jetpack Compose(Android原生)与Compose‑Multiplatform最核心区别是什么?
答案:
Jetpack Compose深度绑定Android系统框架,仅支持Android;
Compose‑Multiplatform基于KMP,渲染引擎独立;同一套Compose UI可以编译到Android、桌面,正在完善iOS;但各平台系统能力依然需要expect‑actual做适配。
解读:
二者的Compose语法几乎一样;底层渲染和平台绑定程度不一样。

本节课知识点总结

  1. Jetpack Compose是Android专属;Compose‑Multiplatform(KMP)实现跨Android、桌面,iOS持续演进;二者UI语法基本一致。
  2. KMP推荐工程架构:shared共享模块存放UI业务;androidApp与desktopApp作为平台外壳;Android依靠Activity;桌面以main函数、application+Window作为程序入口。
  3. expect‑actual声明‑实际机制,用来隔离平台差异化API;common层只做抽象;各平台源集完成具体实现。
  4. 不要幻想完全零适配跨平台;系统权限、文件、弹窗依然存在平台差异,必须针对性处理。
  5. 新版KMP已经支持统一资源管理,新项目优先采用新版资源方案,减少多平台资源维护负担。

📌到此【Jetpack Compose基础语法学与练】全套20课完结。

Logo

一站式 AI 云服务平台

更多推荐