Home > Mobile >  Implementing Dao Crashes the App (Kotlin)
Implementing Dao Crashes the App (Kotlin)

Time:07-13

I've been following an Android App Development tutorial on Udemy and was working on getting the room database working.

Link to the GitHub: https://github.com/tutorialseu/RoomDatabaseDemo/tree/169_completing_the_demo

For some reason, the following line causes the app to crash once loaded. I have tried to follow the tutorial as closely as I can and even copied some parts of the code, and yet nothing seems to work.

val employeeDao = (application as EmployeeApp).db.employeeDao()

Below are the rest of the codes:

(Main Activity)

package com.example.roomdatabasedemo

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.lifecycle.lifecycleScope
import com.example.roomdatabasedemo.databinding.ActivityMainBinding
import kotlinx.coroutines.launch

class MainActivity : AppCompatActivity() {

    private var binding: ActivityMainBinding? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding?.root)

        val employeeDao = (application as EmployeeApp).db.employeeDao()

        binding?.btnAdd?.setOnClickListener {
            addRecord(employeeDao)
        }
    }

    private fun addRecord(employeeDao: EmployeeDao) {
        val name = binding?.etName?.text.toString()
        val email = binding?.etEmailId?.text.toString()

        if (name.isNotEmpty() && email.isNotEmpty()) {
            lifecycleScope.launch {
                employeeDao.insert(EmployeeEntity(name = name, email = email))
                Toast.makeText(
                    applicationContext,
                    "Record saved.",
                    Toast.LENGTH_SHORT
                ).show()
                binding?.etName?.text?.clear()
                binding?.etEmailId?.text?.clear()
            }
        }
        else {
            Toast.makeText(
                applicationContext,
                "Name or Email cannot be blank.",
                Toast.LENGTH_SHORT
            ).show()
        }
    }
}

(Database)

package com.example.roomdatabasedemo

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

@Database(entities = [EmployeeEntity::class], version = 2)
abstract class EmployeeDatabase: RoomDatabase() {

    abstract fun employeeDao(): EmployeeDao

    companion object {
        @Volatile
        private var INSTANCE: EmployeeDatabase? = null

        fun getInstance(context: Context): EmployeeDatabase {
            synchronized(this) {
                var instance = INSTANCE

                if (instance == null) {
                    instance = Room.databaseBuilder(
                        context.applicationContext,
                        EmployeeDatabase::class.java,
                        "employee_database"
                    ).fallbackToDestructiveMigration().build()
                    INSTANCE = instance
                }
                return instance
            }
        }
    }
}

(Dao)

package com.example.roomdatabasedemo

import androidx.room.*
import kotlinx.coroutines.flow.Flow

@Dao
interface EmployeeDao {
    @Insert
    suspend fun insert(employeeEntity: EmployeeEntity)

    @Update
    suspend fun update(employeeEntity: EmployeeEntity)

    @Delete
    suspend fun delete(employeeEntity: EmployeeEntity)

    @Query("SELECT * FROM `employee-table`")
    fun fetchAllEmployees(): Flow<List<EmployeeEntity>>

    @Query("SELECT * FROM `employee-table` where id=:id")
    fun fetchEmployeebyId(id: Int): Flow<List<EmployeeEntity>>
}

(Entity)

package com.example.roomdatabasedemo

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "employee-table")
data class EmployeeEntity(
    @PrimaryKey(autoGenerate = true)
    var id: Int=0,
    var name: String="",
    @ColumnInfo(name = "email-id")
    var email: String=""
)

(App)

package com.example.roomdatabasedemo

import android.app.Application

class EmployeeApp: Application() {
    val db by lazy {
        EmployeeDatabase.getInstance(this)
    }
}

(Android Manifest)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.roomdatabasedemo">

    <application
        android:allowBackup="true"
        android:name=".EmployeeApp"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.RoomDatabaseDemo"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

(gradle:app)

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'kotlin-kapt'
}

android {
    compileSdk 32

    defaultConfig {
        applicationId "com.example.roomdatabasedemo"
        minSdk 24
        targetSdk 32
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled 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 {
        viewBinding true
    }
}

dependencies {

    implementation 'androidx.room:room-runtime:2.4.2'
    annotationProcessor 'androidx.room:room-compiler:2.4.2'
    implementation('androidx.room:room-ktx:2.4.2')

    implementation 'androidx.activity:activity-ktx:1.5.0'

    implementation 'androidx.core:core-ktx:1.8.0'
    implementation 'androidx.appcompat:appcompat:1.4.2'
    implementation 'com.google.android.material:material:1.6.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

(gradle: module)

// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
    id 'com.android.application' version '7.2.0' apply false
    id 'com.android.library' version '7.2.0' apply false
    id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

Below is the error message I got when I tried to debug it.

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.roomdatabasedemo, PID: 30895
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.roomdatabasedemo/com.example.roomdatabasedemo.MainActivity}: java.lang.RuntimeException: cannot find implementation for com.example.roomdatabasedemo.EmployeeDatabase. EmployeeDatabase_Impl does not exist
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4035)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4201)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2438)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loopOnce(Looper.java:226)
        at android.os.Looper.loop(Looper.java:313)
        at android.app.ActivityThread.main(ActivityThread.java:8663)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:567)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
     Caused by: java.lang.RuntimeException: cannot find implementation for com.example.roomdatabasedemo.EmployeeDatabase. EmployeeDatabase_Impl does not exist
        at androidx.room.Room.getGeneratedImplementation(Room.java:100)
        at androidx.room.RoomDatabase$Builder.build(RoomDatabase.java:1486)
        at com.example.roomdatabasedemo.EmployeeDatabase$Companion.getInstance(EmployeeDatabase.kt:26)
        at com.example.roomdatabasedemo.EmployeeApp$db$2.invoke(EmployeeApp.kt:7)
        at com.example.roomdatabasedemo.EmployeeApp$db$2.invoke(EmployeeApp.kt:6)
        at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
        at com.example.roomdatabasedemo.EmployeeApp.getDb(EmployeeApp.kt:6)
        at com.example.roomdatabasedemo.MainActivity.onCreate(MainActivity.kt:19)
        at android.app.Activity.performCreate(Activity.java:8290)
        at android.app.Activity.performCreate(Activity.java:8270)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1329)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4009)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4201) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2438) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loopOnce(Looper.java:226) 
        at android.os.Looper.loop(Looper.java:313) 
        at android.app.ActivityThread.main(ActivityThread.java:8663) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:567) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135) 

Please help me with what went wrong with line "val employeeDao = (application as EmployeeApp).db.employeeDao()". Sorry for making the question vague. I am very inexperienced in this field and have no idea how to specify the issue further.

Any help will be appreciated.

CodePudding user response:

Use these implementations for room

implementation 'androidx.room:room-runtime:2.4.2'
kapt 'androidx.room:room-compiler:2.4.2'
implementation 'androidx.room:room-ktx:2.4.2'

Put these in your app/build.gradle

CodePudding user response:

Looks like I have messed up in the Gradle file. I had to use version 1.5 of the following dependency (and not above) for the app to work.

classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.32"

  • Related