Yes I have already tried some old guides, I described it below.
I created new project for Room Database in Kotlin Android. I followed the official google documentation for it.
https://developer.android.com/training/data-storage/room
If I follow as per documentation I get error
java.lang.RuntimeException: cannot find implementation for com.example.laptopsdb.AppDatabase. AppDatabase_Impl does not exist
I also tried changing room-runtime to room-ktx but the error is same. Moreover, I tried adding id 'kotlin-kapt' and changing annotationProcessor to kapt but that give me following error, errors actually, bunch of them, while auto opening UserDao.java file
https://github.com/subjectOneThree/StackOverFLowShares/blob/main/Screenshot_20220715_215040.png
My code is almost stock according to documentation, however you can checkout if I made any stupid mistake
build.gradle (app)
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
//id 'kotlin-kapt'
}
android {
compileSdk 32
defaultConfig {
applicationId "com.example.laptopsdb"
minSdk 21
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'
}
}
dependencies {
apply plugin: "kotlin-kapt"
implementation 'androidx.core:core-ktx:1.7.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'
def room_version = "2.4.2"
//implementation "androidx.room:room-ktx:$room_version"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
//kapt "androidx.room:room-compiler:$room_version"
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
}
User.kt
@Entity (tableName = "laptops")
data class User(
@PrimaryKey val uid: Int,
@ColumnInfo(name = "first_name") val firstName: String?,
@ColumnInfo(name = "last_name") val lastName: String?
)
UserDao.kt
@Dao
interface UserDao {
@Query("SELECT * FROM laptops")
suspend fun getAll(): List<User>
@Query("SELECT * FROM user WHERE uid IN (:userIds)")
suspend fun loadAllByIds(userIds: IntArray): List<User>
@Query("SELECT * FROM user WHERE first_name LIKE :first AND "
"last_name LIKE :last LIMIT 1")
suspend fun findByName(first: String, last: String): User
@Insert
suspend fun insertAll(vararg users: User)
@Delete
suspend fun delete(user: User)
}
AppDatabase.kt
@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val db = Room.databaseBuilder(
applicationContext,
AppDatabase::class.java, "laptops"
).build()
val userDao = db.userDao()
GlobalScope.launch(Dispatchers.Default) {
userDao.insertAll(User(2,"Hello","World"))
val users: List<User> = userDao.getAll()
Log.d("Room Activity", users.toString())
}
}
}
Some of the older project, and a project from my friend have exactly the same code (as far as I have looked into it) and they are working fine. But now when I am trying to create new project it is giving me error. I have tried building several projects before posting here.
CodePudding user response:
- (comment) doing this:
val db = Room.databaseBuilder(
applicationContext,
AppDatabase::class.java, "laptops"
).build()
in the onCreate of mainActivity is a very bad way of creating a database instance, unless you want multiple database instances in one app!
- solution:
try changing your build.gradle to this:
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
apply plugin: 'kotlin-kapt'
android {
compileSdk 32
defaultConfig {
applicationId "com.example.laptopsdb"
minSdk 21
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'
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.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'
def room_version = "2.4.2"
kapt("androidx.room:room-compiler:2.4.2")
implementation("androidx.room:room-runtime:2.4.2")
implementation("androidx.room:room-ktx:2.4.2")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
}
EDIT: After creating a project with the same code you have I noticed some rather strange bugs:
in your User.kt file you declared the table name of that entity to "laptops", but in your UserDao you still refered to a table named user, which does not exist (???), that's why room had some troubles with your dao
You declare your uid as Primary Key, which SHOULD NEVER be a duplicate, every single one of the keys should differ, yet in your main activity you use "userDao.insertAll(User(2,"Hello","World"))", which will result in a crash on second run, just remove that line
using "GlobalScope.launch(Dispatchers.Default)" to run a coroutine isn't really encouraged, GlobalScope is even marked in the android studio as a delicate API and using it without proper knowledge first may result in strange bugs or even memory leaks, just use a viewModel to handle all of the work
As I also stated before,
val db = Room.databaseBuilder(
applicationContext,
AppDatabase::class.java, "laptops"
).build()
do not use that to create database instance
- update your build.gradle to:
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
apply plugin: 'kotlin-kapt'
android {
compileSdk 32
defaultConfig {
applicationId "com.example.laptopsdb"
minSdk 21
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'
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.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'
// you may add the variable, just keep the version correct
implementation "androidx.room:room-runtime:2.5.0-alpha02"
implementation "androidx.room:room-ktx:2.5.0-alpha02"
kapt "androidx.room:room-compiler:2.5.0-alpha02"
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
}
and the dao to:
@Dao
interface UserDao {
@Query("SELECT * FROM laptops")
suspend fun getAll(): List<User>
@Query("SELECT * FROM laptops WHERE uid IN (:userIds)")
suspend fun loadAllByIds(userIds: IntArray): List<User>
@Query("SELECT * FROM laptops WHERE first_name LIKE :first AND "
"last_name LIKE :last LIMIT 1")
suspend fun findByName(first: String, last: String): User
@Insert
suspend fun insertAll(vararg users: User)
@Delete
suspend fun delete(user: User)
}