user2024
user2024

Reputation: 39

Room.kt - Database_Impl does not exist

I am trying to implement Database in a fresh app, but for some reason it's crashing and after a lot of searches I am posting this issue, I did not find anything relevant:

FATAL EXCEPTION: main (Ask Gemini)
    Process: com.basic.app, PID: 19092
    java.lang.RuntimeException: Cannot find implementation for com.basic.app.data.MyDatabase. MyDatabase_Impl does not exist
        at androidx.room.Room.getGeneratedImplementation(Room.kt:58)
        at androidx.room.RoomDatabase$Builder.build(RoomDatabase.kt:1351)
        at com.basic.app.data.DatabaseProvider.getDatabase(DatabaseProvider.kt:18)
        at com.basic.app.MainActivity$onCreate$1$1$1.invoke(MainActivity.kt:44)
        at com.basic.app.MainActivity$onCreate$1$1$1.invoke(MainActivity.kt:36)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:117)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
        at androidx.compose.material3.ScaffoldKt$ScaffoldLayout$1$1$1$bodyContentPlaceables$1.invoke(Scaffold.kt:239)
        at androidx.compose.material3.ScaffoldKt$ScaffoldLayout$1$1$1$bodyContentPlaceables$1.invoke(Scaffold.kt:221)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
        at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$subcompose$3$1$1.invoke(SubcomposeLayout.kt:1067)
        at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$subcompose$3$1$1.invoke(SubcomposeLayout.kt:701)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108)
        at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
        at androidx.compose.runtime.ActualJvm_jvmKt.invokeComposable(ActualJvm.jvm.kt:78)
        at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3340)
        at androidx.compose.runtime.ComposerImpl.composeContent$runtime_release(Composer.kt:3273)
        at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:588)
        at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:1013)
        at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:4007)
        at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:520)
        at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcomposeInto(SubcomposeLayout.kt:721)
        at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose(SubcomposeLayout.kt:694)
        at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose(SubcomposeLayout.kt:685)
        at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose(SubcomposeLayout.kt:669)
        at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$Scope.subcompose(SubcomposeLayout.kt:1014)
        at androidx.compose.material3.ScaffoldKt$ScaffoldLayout$1$1$1.invoke(Scaffold.kt:221)
        at androidx.compose.material3.ScaffoldKt$ScaffoldLayout$1$1$1.invoke(Scaffold.kt:128)
        at androidx.compose.ui.layout.MeasureScope$layout$1.placeChildren(MeasureScope.kt:70)
        at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$createMeasurePolicy$1$measure$1.placeChildren(SubcomposeLayout.kt:879)
        at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildren$1$1.invoke(LayoutNodeLayoutDelegate.kt:365)
        at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate$layoutChildren$1$1.invoke(LayoutNodeLayoutDelegate.kt:357)
        at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2299)
        at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:467)
        at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:230)
        at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133)
        at androidx.compose.ui.node.OwnerSnapshotObserver.observeLayoutSnapshotReads$ui_release(OwnerSnapshotObserver.kt:83)
        at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.layoutChildren(LayoutNodeLayoutDelegate.kt:357)

Here is my main activity code:

class MainActivity : ComponentActivity() {

    private lateinit var database: MyDatabase
    private lateinit var activityRepository: ActivityRepository

    @SuppressLint("CoroutineCreationDuringComposition")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            WalkathonTheme {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    Greeting(
                            name = "Android",
                            modifier = Modifier.padding(innerPadding)
                    )

                    if (!::database.isInitialized) {
                        database = DatabaseProvider.getDatabase(this)
                    }

                    // Initialize activityRepository if not already initialized
                    if (!::activityRepository.isInitialized) {
                        database.let { db ->
                            activityRepository = ActivityRepository(db.activityDao())
                        }
                    }

                    // Fetch all activities asynchronously
                    GlobalScope.launch(Dispatchers.IO) {
                        val activities = activityRepository.all()
                        // Loop through the activities
                        for (activity in activities) {
                            // Perform operations with each activity
                            Log.d("MainActivity", "Activity: $activity")
                        }
                    }
                }
            }
        }
    }
}

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    Text(
            text = "Hello $name!",
            modifier = modifier
    )
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    WalkathonTheme {
        Greeting("Android")
    }
}

Here is my Dao:

import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update

@Dao
interface ActivityDao {
    @Insert
    suspend fun insert(activity: ActivityModel)

    @Update
    suspend fun update(activity: ActivityModel)

    @Delete
    suspend fun delete(activity: ActivityModel)

    @Query("SELECT * FROM activity")
    suspend fun all(): List<ActivityModel>
}

Here is my model:

import androidx.room.Entity
import androidx.room.PrimaryKey
import java.util.Date

@Entity(tableName = "activity")
data class ActivityModel(
    @PrimaryKey(autoGenerate = true)
    val id: Long = 0,
    val steps: Int,
    val createdAt: Date,
    val updatedAt: Date? = null
)

Here is my repository:

class ActivityRepository(private val activityDao: ActivityDao) {
    suspend fun all(): List<ActivityModel> {
        return activityDao.all()
    }
}

Here is my Database:

import androidx.room.Database
import androidx.room.RoomDatabase

@Database(entities = [ActivityModel::class], version = 1)
abstract class MyDatabase : RoomDatabase() {
    abstract fun activityDao(): ActivityDao
}

Here is my DatabaseProvider:

import android.content.Context
import androidx.room.Room

object DatabaseProvider {

    private var INSTANCE: MyDatabase? = null

    fun getDatabase(context: Context): MyDatabase {
        synchronized(this) {
            if (INSTANCE == null) {
                INSTANCE = Room.databaseBuilder(
                    context.applicationContext,
                    MyDatabase::class.java,
                    context.getString(R.string.database_name)
                ).build()
            }
            return INSTANCE!!
        }
    }
}

Here is my gradle:

plugins {
    alias(libs.plugins.android.application)
    alias(libs.plugins.jetbrains.kotlin.android)
}

android {
    namespace = "com.basic.app"
    compileSdk = 34

    defaultConfig {
        applicationId = "com.basic.app"
        minSdk = 29
        targetSdk = 34
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables {
            useSupportLibrary = true
        }
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
    buildFeatures {
        compose = true
    }
    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.1"
    }
    packaging {
        resources {
            excludes += "/META-INF/{AL2.0,LGPL2.1}"
        }
    }
}

dependencies {
    implementation(libs.androidx.core.ktx)
    implementation(libs.androidx.lifecycle.runtime.ktx)
    implementation(libs.androidx.activity.compose)
    implementation(platform(libs.androidx.compose.bom))
    implementation(libs.androidx.ui)
    implementation(libs.androidx.ui.graphics)
    implementation(libs.androidx.ui.tooling.preview)
    implementation(libs.androidx.material3)
    implementation(libs.androidx.room.common)
    implementation(libs.androidx.room.ktx)
    testImplementation(libs.junit)
    androidTestImplementation(libs.androidx.junit)
    androidTestImplementation(libs.androidx.espresso.core)
    androidTestImplementation(platform(libs.androidx.compose.bom))
    androidTestImplementation(libs.androidx.ui.test.junit4)
    debugImplementation(libs.androidx.ui.tooling)
    debugImplementation(libs.androidx.ui.test.manifest)
}

Version catalog:

[versions]
agp = "8.4.1"
kotlin = "1.9.0"
coreKtx = "1.10.1"
junit = "4.13.2"
junitVersion = "1.1.5"
espressoCore = "3.5.1"
lifecycleRuntimeKtx = "2.6.1"
activityCompose = "1.8.0"
composeBom = "2023.08.00"
roomCommon = "2.6.1"
roomCompiler = "2.6.1"
roomKtx = "2.6.1"
roomRuntime = "2.6.1"

[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "roomCompiler" }
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "roomRuntime" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-ui = { group = "androidx.compose.ui", name = "ui" }
androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
androidx-room-common = { group = "androidx.room", name = "room-common", version.ref = "roomCommon" }
androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "roomKtx" }

[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }

I wanted to run the app successfully, but it's crashing.

Upvotes: 1

Views: 170

Answers (1)

JustSightseeing
JustSightseeing

Reputation: 3025

Actually @Majedul Islam was correct, just failed to show how to add the dependency correctly:

in build.gradle to plugin block add:kotlin("kapt") like so:

plugins {
    alias(libs.plugins.android.application)
    alias(libs.plugins.jetbrains.kotlin.android)
    kotlin("kapt")
}

then in dependencies add kapt(libs.androidx.room.compiler) as you were missing only this one

in the end make sure all 3 of those dependencies are there (don't add all 3 as you had some of them)

    implementation(libs.androidx.room.common)
    implementation(libs.androidx.room.ktx)
    kapt(libs.androidx.room.compiler)

and it fixes your problem, however it will still not build since you're using a Date in your entity (and that requires a type converter)

so create a class Converter

class Converters {
    @TypeConverter
    fun fromTimestamp(value: Long?): Date? {
        return value?.let { Date(it) }
    }

    @TypeConverter
    fun dateToTimestamp(date: Date?): Long? {
        return date?.time?.toLong()
    }
}

and in your database add: @TypeConverters(Converters::class) so it looks like this:

@Database(entities = [ActivityModel::class], version = 1)
@TypeConverters(Converters::class)
abstract class Database : RoomDatabase() {
    abstract fun activityDao(): ActivityDao
}

Upvotes: 0

Related Questions