RoomDatabaseConstructor on KotlinMultiplatform has no corresponding expected declaration
Asked Answered
Y

1

8

I have implemented the latest version of Room in my KMP project (roomCommon = "2.7.0-alpha06" ). The new version change the instantiation setup for a RoomDatabase in a KMP project

https://developer.android.com/jetpack/androidx/releases/room#2.7.0-alpha06

Now we have to implement RoomDatabaseConstructor.

So that's my database file on commonMain directory:

import androidx.room.ConstructedBy
import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.RoomDatabaseConstructor
import data.database.dao.UserPreferencesDAO
import data.database.entities.UserPreferencesEntity

const val DATABASE_NAME = "app_database.db"

expect object MyDatabaseCtor : RoomDatabaseConstructor<AppDatabase>

@Database(entities = [UserPreferencesEntity::class], version = 1)
@ConstructedBy(MyDatabaseCtor::class)
abstract class AppDatabase : RoomDatabase(), DB {
    abstract fun getDao(): UserPreferencesDAO
    override fun clearAllTables(): Unit {}
}

interface DB {
    fun clearAllTables(): Unit {}
}

Them, after that I have implemented my actual functions on androidMain and iosMain

iOS:

actual object MyDatabaseCtor : RoomDatabaseConstructor<AppDatabase> {
    override fun initialize(): AppDatabase {
        return getDatabase()
    }
}

fun getDatabase(): AppDatabase {
    return Room.databaseBuilder<AppDatabase>(name = DATABASE_NAME).setDriver(BundledSQLiteDriver())
        .setQueryCoroutineContext(Dispatchers.IO).build()
}

Android:

actual object MyDatabaseCtor : RoomDatabaseConstructor<AppDatabase>{

    private val appContext = RickMortyApp.context
    override fun initialize(): AppDatabase {
        val dbFile = appContext.getDatabasePath(DATABASE_NAME)
        return Room.databaseBuilder<AppDatabase>(appContext, dbFile.absolutePath)
            .setDriver(BundledSQLiteDriver())
            .setQueryCoroutineContext(Dispatchers.IO)
            .build()
    }
}

The problem is when I build the code I get a autogenerated class

public actual object MyDatabaseCtor : RoomDatabaseConstructor<AppDatabase> {
  override fun initialize(): AppDatabase = `data`.database.AppDatabase_Impl()
}

And my Actual/Expected classes start to fail with the next message:

**Error1:**

project/composeApp/build/generated/ksp/metadata/commonMain/kotlin/data/database/MyDatabaseCtor.kt:5:22 'actual object MyDatabaseCtor : RoomDatabaseConstructor<AppDatabase>' has no corresponding expected declaration

**Error 2:**

Redeclaration:
actual object MyDatabaseCtor : RoomDatabaseConstructor<AppDatabase>

**Error 3:**

/composeApp/src/androidMain/kotlin/data/database/Database.android.kt:13:15 'actual object MyDatabaseCtor : RoomDatabaseConstructor<AppDatabase>' has no corresponding expected declaration

I tried to clean project to remove de autogenerated class but after compile is the same error class.

Yerga answered 11/8, 2024 at 16:14 Comment(2)
Same here. I also noticed this warning on the expect version of the Constructor. Looks like maybe they didn't test these updates with Kotlin 2.0? """Object 'DatabaseConstructor': expect and corresponding actual are declared in the same module, which will be prohibited in Kotlin 2.0. See youtrack.jetbrains.com/issue/KT-55177"""Maganmagana
@Maganmagana if you don't run KSP on commonMain, that error disappearsVltava
M
1

Ok I think I figured this out.

I replaced this line

dependencies.kspCommonMainMetadata(libs.room.compiler)

with this:

dependencies {
    listOf(
        "kspAndroid",
        // "kspJvm",
        "kspIosSimulatorArm64",
        "kspIosX64",
        "kspIosArm64"
    ).forEach {
        add(it, libs.room.compiler)
    }
}

Based on the advice here: https://issuetracker.google.com/issues/342905180#comment21

I also removed this code which was a workaround for errors in the previous version

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask<*>>().configureEach {
    if (name != "kspCommonMainKotlinMetadata") {
        dependsOn("kspCommonMainKotlinMetadata")
    }
}

For some reason JVM is still not working with this error, which is why I have it commented out for the moment: Configuration with name 'kspJvm' not found.

Maganmagana answered 12/8, 2024 at 4:25 Comment(3)
I get another errro: Cannot change attributes of configuration ':composeApp:debugFrameworkIosX64' after it has been locked for mutationNoni
Nope, doesn't work.Liberati
This approach above doesn't work for me.Unmusical

© 2022 - 2025 — McMap. All rights reserved.