这里写目录标题
代码仓库
本小节代码已经上传到gitee,请自行查看:
点击访问仓库
KMP 框架
基本框架
源码集合 | 描述 | 存放内容示例 |
---|---|---|
androidMain | 针对 Android 平台的代码 | 使用 Android SDK、Android 特定的 API 和 UI 组件 |
desktopMain | 针对桌面平台(Windows、macOS、Linux)的代码 | 使用 JavaFX、Swing 或其他桌面 GUI 框架的代码 |
commonMain | 跨平台的用户界面代码,使用 Compose Multiplatform 框架 | 定义可在 Android、iOS、桌面等多个平台上共享的 UI 组件 |
nativeMain | 原生代码,直接访问底层系统 API 或使用特定于平台的库的代码 | 使用 POSIX 接口、平台特定的库或服务 |
actual&expect
KMP使用两个关键词actual和expect实现了跨平台开发;
- expect一般在commonApp里面定义,这是整个项目的通用逻辑部分,它相当于一个抽象类;
- actual一般在desktopApp或androidApp里面定义,它是对expect定义的函数或者变量的具体实现,这样就可以实现了每一个平台都有不同的各自对应的处理函数逻辑;
例如,先在commonApp下创建一个文件 BatteryManager.kt
该文件定义了获取当前设备电量剩余多少的方法;
expect class BatteryManager {
fun getBatteryLevel(): Int
}
之后就到各个平台的实现层进行该方法的具体逻辑实现;
比如我在androidApp层实现了该方法,同样的,你需要在对应的位置创建一样名称的文件,用来对该expect定义的类进行相应的actual实现(你可以使用AndroidStudio的自动创建功能实现这一步骤)
/**
* 实现电池管理功能的类
*
* @param context 应用程序上下文,用于获取电池信息
*/
actual class BatteryManager(
private val context: Context
) {
/**
* 获取电池电量百分比
*
* 通过广播接收器获取电池状态,并计算电池电量百分比
*
* @return 电池电量百分比(0-100)
*/
actual fun getBatteryLevel(): Int {
// 创建一个意图过滤器,用于匹配电池状态改变的广播
val intentFilter = IntentFilter(Intent.ACTION_BATTERY_CHANGED)
// 使用广播接收器接收电池状态的广播,这里不需要创建一个具体的接收器对象
val batteryStatus = context.registerReceiver(null, intentFilter)
// 从广播意图中获取电池电量级别,如果没有提供则默认为-1
val level = batteryStatus?.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) ?: -1
// 从广播意图中获取电池电量的缩放值,如果没有提供则默认为-1
val scale = batteryStatus?.getIntExtra(BatteryManager.EXTRA_SCALE, -1) ?: -1
// 计算并返回电池电量百分比
return (level / scale.toFloat() * 100).roundToInt()
}
}
actual class BatteryManager {
actual fun getBatteryLevel(): Int {
val systemInfo = SystemInfo()
val batteryLevel = systemInfo.hardware.powerSources.firstOrNull()
return batteryLevel?.remainingCapacityPercent?.times(100)?.roundToInt() ?: -1
}
}
Koin 依赖注入管理
此部分使用koin框架实现基本的依赖注入管理,采用MVVM架构
下图展示了下面案例使用Koin框架的整体逻辑架构图,下面对逻辑进行简要陈述
- startKoin用于初始化整个Koin框架,在这里需要定义配置以及注册对应的modules模块
- 每一个module都管理者多个repository以及viewmodel
- 下图中sharedModule模块注册了DbRepo单例,并同时注册了DbVM
- DbRepo相当于MVC的Service层,用于仓储等底层逻辑的操作,他有一个对应的实现类DbRepoImpl
- DbVM相当于MVC的controller层,用于调用Service层内包装好的逻辑方法
- 所以最终我们的App视图实际上是自动注入DbVM后,通过该viewmodel调用对应的方法来执行对应的结果的(具体的代码思路可以参考Springboot的DI思想,这里不做过多阐述)
commonApp层
在KMP开发过程中,所有逻辑都必须先从commonApp层定义,然后再扩展到各个平台实现层来完善具体代码;
首先导入koin依赖,因为我们这边使用DSL进行依赖管理,所以需要先在libs.vers