背景
- 最近通过Compose写android/ios 一体式应用, 只要通过compose书写ui+两端平台差异化代码即可实现跨平台应用,这篇文章主要分享在开发过程中遇到的问题。
编译问题
问题一:提示找不到kspIosX64
sync过程中提示找不到kspIosX64这个系统版本,原因是commonMain的build.gradle.kts文件没有支持上iosX64,添加上iosX64即可。
add("kspIosX64", libs.androidx.room.compiler)提示找不到kspIosX64
解决办法
下面截图中添加绿色框内容即可

问题二:exit code: PROCESSING_ERROR
在接入room跨平台数据库后,编译ksp的android插件时候报错。主要错误原因是因为我@Database修饰的entities类,不是用@Entity修饰的类,而是一个普通的class类。
Caused by: java.lang.Exception: KSP failed with exit code: PROCESSING_ERROR
at com.google.devtools.ksp.gradle.KspAAWorkerAction.execute(KspAATask.kt:643)
at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:63)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:66)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:62)
at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:100)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:62)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
解决办法
这里定义的存储类错误了,应该是需要@Entity修饰的类,改成TodoEntity(@Entity)类即可解决上述报错问题。

学习补充注意:room跨平台文档
问题三:ios编译遇到错误@ConstructedBy definition must be an 'expect' declaration.
错误详细信息如下,这里错误的原因是因为我下面的getAllCourseByYearAndMonth方法是通过Flow函数来实现的,在Android上编译运行都没问题,但是iOS平台所有的@Dao修饰的函数都必须用suspend来修饰,所以不支持Flow写法。
//错误详细内容
e: [ksp] /Users/admin/Library/kotlin_project/music_record/composeApp/src/iosMain/kotlin/com/music/classroom/db/Database.ios.kt:61: The @ConstructedBy definition must be an 'expect' declaration.
//代码错误地方
@Query("SELECT * FROM TodoEntity WHERE year =:year and month =:month")
fun getAllCourseByYearAndMonth(year: Int, month: Int): Flow<List<TodoEntity>>
解决办法
这里只需要把getAllCourseByYearAndMonth的Flow去掉,添加上suspend挂起即可。
@Query("SELECT * FROM TodoEntity WHERE year =:year and month =:month")
suspend fun getAllCourseByYearAndMonth(year: Int, month: Int): List<TodoEntity>
使用问题
问题一:数据库没办法使用
-
根据上面room文档写入对应依赖后,发现没办法对接到compose页面中,android提示为初始化/ios提示指针异常。其中缺少最关键代码,room文档是有提出来(room如何实例化数据库),但是没有告诉我们具体该如何使用(后面看他们提供demo才知道正确用法)。
room如何实例化数据库
解决办法
- 首先通过expect声明跨平台差异函数,需要在androidMain/iosMain分别实现对应函数,但是官网的ksp:2.2.21-2.0.4 + room:2.8.3已经可以自动生成差异化函数了,所以都不需要我们自己去实现AppDatabaseConstructor函数,编译过程会生成。
@Database(entities = [TodoEntity::class], version = 1)
@ConstructedBy(AppDatabaseConstructor::class)
abstract class AppDatabase : RoomDatabase() {
abstract fun getDao(): TodoDao
}
// The Room compiler generates the `actual` implementations.
@Suppress("KotlinNoActualForExpect")
expect object AppDatabaseConstructor : RoomDatabaseConstructor<AppDatabase> {
override fun initialize(): AppDatabase
}
-
上面第一步生成了差异化代码了,我们该如何实例化数据库呢?我们需要通过Room.databaseBuilder<AppDatabase(看你定义名字)>来实例化我们的数据库(这里图【room如何实例化数据库】),只不过官网没有详细说到是通过Room.databaseBuilder来回去对应的Builder
image.png 在原生层实例化化数据库对象要如何传递到下面子Compose View里面呢?这里我们就需要用到CompositionLocalProvider来实现了,我这里的LocalAppContainer是放在commonMain模块下的object class,provides意思是LocalAppContainer这个变量的值来源于AppContainer(iOS也类似这样子实现,这里留个动手机会给大家)。
注意:提供provider给下面所有子View访问对应属于(必须在setContent下面)

class MusicApplication: Application() {
lateinit var container: AppContainer
override fun onCreate() {
super.onCreate()
AppUtils.application = this
container = AppContainer(Factory(this))
}
}
class AppContainer(
private val factory: Factory,
) {
val dataRepository: CourseRepository by lazy {
CourseRepository(
database = factory.createRoomDatabase(),
scope = CoroutineScope(Dispatchers.Default + SupervisorJob()),
)
}
}
- 直接在commonMain模块下的Compose 函数调用即可。
@Composable
fun AllCourse() {
val db = LocalAppContainer.current.dataRepository
……
val response = db.getAllCoursesByYearAndMonth(year, month)
}
版本分享
分享下当前编译通过版本:
//libs.version.toml
agp = "8.11.2"
android-compileSdk = "36"
android-minSdk = "24"
android-targetSdk = "36"
androidx-activity = "1.11.0"
androidx-appcompat = "1.7.1"
androidx-core = "1.17.0"
androidx-espresso = "3.7.0"
androidx-lifecycle = "2.9.4"
androidx-navigation = "2.9.1"
androidx-testExt = "1.3.0"
composeMultiplatform = "1.9.0"
junit = "4.13.2"
kotlin = "2.2.20"
room = "2.8.3"
sqlite = "2.6.1"
ksp = "2.2.21-2.0.4"
成果分享


