Skip to content

桌面端进阶 (Mac/Win/Linux)

源:Kotlin Multiplatform 官方文档

开发跨平台桌面应用时,仅仅靠 Compose Multiplatform 的 UI 是不够的。本章将展示如何调用各操作系统的深层 API,实现系统集成、底层优化和硬件交互。

macOS 深度集成:Cocoa 框架实战

macOS 拥有强大的 AppKit 框架。通过 Kotlin/Native 的 Objective-C 互操作,我们可以直接调用它。

实战:调用原生文件选择器 (NSSavePanel)

kotlin
// macosMain
import platform.AppKit.*
import platform.Foundation.*

fun showNativeSavePanel(onFileSelected: (String) -> Unit) {
    val panel = NSSavePanel.savePanel()
    panel.title = "请选择保存位置"
    panel.allowedFileTypes = listOf("txt", "json")
    
    if (panel.runModal() == NSModalResponseOK) {
        val path = panel.URL?.path
        if (path != null) onFileSelected(path)
    }
}

Windows 深度集成:Win32 API 与注册表

Windows 应用往往需要通过 注册表 (Registry) 来存储配置或实现开机自启。

实战:读写注册表 (Win32)

kotlin
// mingwMain
import platform.windows.*
import kotlinx.cinterop.*

fun setAutoStart(appName: String, exePath: String) {
    memScoped {
        val hKey = alloc<HKEYVar>()
        val subKey = "Software\Microsoft\Windows\CurrentVersion\Run"
        
        // 打开注册表项
        if (RegOpenKeyExW(HKEY_CURRENT_USER, subKey, 0u, KEY_WRITE, hKey.ptr) == ERROR_SUCCESS) {
            val pathPtr = exePath.wcstr // 转换为宽字符指针
            // 设置键值
            RegSetValueExW(hKey.value, appName, 0u, REG_SZ.toUInt(), 
                pathPtr.ptr.reinterpret(), (exePath.length * 2 + 2).toUInt())
            RegCloseKey(hKey.value)
        }
    }
}

Linux 深度集成:POSIX 与 /proc 文件系统

在 Linux 环境下,获取系统状态最准确的方式是直接读取 /proc 虚拟文件系统。

实战:获取系统 CPU 负载 (C 标准库 + POSIX)

kotlin
// linuxMain
import platform.posix.*

fun getCpuLoad(): Double {
    val file = fopen("/proc/loadavg", "r") ?: return -1.0
    val buffer = ByteArray(64)
    // 直接读取 POSIX 文件流
    fgets(buffer.refTo(0), buffer.size, file)
    fclose(file)
    
    val content = buffer.toKString()
    return content.split(" ").firstOrNull()?.toDouble() ?: -1.0
}

跨平台系统托盘 (System Tray) 的实现思路

虽然各平台实现不同,但我们可以在 commonMain 定义统一接口:

kotlin
// commonMain
expect class SystemTrayManager() {
    fun setIcon(resourceName: String)
    fun showNotification(title: String, message: String)
}
  • macOS: 使用 NSStatusBar
  • Windows: 使用 Shell_NotifyIconW (Win32)。
  • Linux: 使用 libappindicator (通过 cinterop)。

性能清单:桌面端优化建议

  1. 减少内存占用: 桌面应用往往长时间运行。在 Kotlin/Native 中,注意利用 memScoped 及时释放 C 指针。
  2. 避免主线程阻塞: 桌面应用的 UI 线程(如 Compose 的 EDT)对延迟极其敏感。执行上述 Win32 或 POSIX 阻塞调用时,务必切换到 Dispatchers.IO
  3. 多窗口通信: 在大型桌面应用中,利用 SharedFlowAtomicFU 构建一个进程内的全局事件总线。