58 votes

Bibliothèque Android Room Persistence et Kotlin

J'essaie d'écrire une application simple en utilisant Kotlin et Bibliothèque de persistance des pièces . J'ai suivi le tutoriel dans le codelab Android Persistence.

Voici mon AppDatabase en Kotlin :

@Database(entities = arrayOf(User::class), version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userModel(): UserDao

    companion object {
        private var INSTANCE: AppDatabase? = null
        @JvmStatic fun getInMemoryDatabase(context: Context): AppDatabase {
            if (INSTANCE == null) {
                INSTANCE = Room.inMemoryDatabaseBuilder(context.applicationContext, AppDatabase::class.java).allowMainThreadQueries().build()
            }
            return INSTANCE!!
        }

        @JvmStatic fun destroyInstance() {
            INSTANCE = null
        }
    }
}

Mais lorsque j'ai essayé de lancer l'application, elle s'est immédiatement écrasée. Voici le journal du crash :

Caused by: java.lang.RuntimeException: cannot find implementation for com.ttp.kotlin.kotlinsample.room.AppDatabase. AppDatabase_Impl does not exist
    at android.arch.persistence.room.Room.getGeneratedImplementation(Room.java:90)
    at android.arch.persistence.room.RoomDatabase$Builder.build(RoomDatabase.java:340)
    at com.ttp.kotlin.kotlinsample.room.AppDatabase$Companion.getInMemoryDatabase(AppDatabase.kt:19)
    at com.ttp.kotlin.kotlinsample.MainKotlinActivity.onCreate(MainKotlinActivity.kt:28)
    at android.app.Activity.performCreate(Activity.java:6272)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2387)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2494) 
    at android.app.ActivityThread.access$900(ActivityThread.java:157) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1356)

Il semble que la classe AppDatabase_Impl n'était pas autogénéré. J'ai vérifié l'application java originale téléchargée depuis codelab et j'ai constaté que AppDatabase_Impl était autogénéré.

Version de Kotlin : 1.1.2-3
Version de la chambre : 1.0.0-alpha1

Quelqu'un a-t-il de l'expérience dans ce domaine ?

Editar: Utilisation de kapt résout mon problème. Dans mon cas, je dois remplacer annotationProcessor con kapt .

2 votes

Pouvez-vous poster votre build.gradle également ?

11 votes

Est-ce qu'il y a apply plugin: 'kotlin-kapt' y kapt "android.arch.persistence.room:compiler:1.0.0-alpha1" dans votre module build.gradle ?

1 votes

Merci. L'utilisation du plugin kapt résout mon problème.

53voto

Nicola De Fiorenze Points 754

Habituellement dans le projet build.gradle Je définis les versions des dépendances :

ext {
    buildToolsVersion = '25.0.2'
    supportLibVersion = '25.3.1'
    espressoVersion = '2.2.2'
    archRoomVersion = '1.0.0-alpha1'
}

donc dans l'application build.gradle les dépendances ressemblent :

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"

    compile "com.android.support:appcompat-v7:${rootProject.supportLibVersion}"

    compile "android.arch.persistence.room:runtime:${rootProject.archRoomVersion}"
    annotationProcessor "android.arch.persistence.room:compiler:${rootProject.archRoomVersion}"
    kapt "android.arch.persistence.room:compiler:${rootProject.archRoomVersion}"

    androidTestCompile("com.android.support.test.espresso:espresso-core:${rootProject.espressoVersion}", {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    testCompile 'junit:junit:4.12'
}

Vous pouvez maintenant définir les entités Daos et la base de données en Kotlin.

Base de données :

@Database(entities = arrayOf(User::class), version = 1)
abstract class Database : RoomDatabase() {
    abstract fun userDao(): UserDao
}

Entité :

@Entity(tableName = "user")
class User {
    @PrimaryKey(autoGenerate = true)
    var id: Int = 0
    var name: String = ""
}

Dao :

@Dao
interface UserDao {
    @Query("SELECT * FROM user")
    fun getAll(): List<User>

    @Insert
    fun insertAll(vararg users: User)

    @Delete
    fun delete(user: User)
}

NB : Requête avec paramètres. Kotlin renomme les paramètres, ainsi la requête SQL pour récupérer tous les emails qui appartiennent à un utilisateur via le userId est :

@Query("SELECT * FROM email "
            + "INNER JOIN user ON user.id = email.userId "
            + "WHERE user.id = :arg0")
    fun getEmailsForUser(userId: Int): List<Email>

1 votes

Merci pour votre aide. Dans mon cas, Kotlin renomme les params en p0, p1... au lieu de arg0, arg1...

0 votes

@Nicola De Fiorenze j'ai le même problème mais l'ajout de kapt introduit quelques erreurs gradle, veuillez regarder ici. stackoverflow.com/questions/44142964/ .

0 votes

Comment puis-je appeler le db.userDao().insertAll(user) ?

39voto

Lyofen Points 462

Dans mon cas, dans build.gradle, lorsque vous avez "annotationProcessor", vous devez le dupliquer avec "kapt" et cela fonctionne.

compile "android.arch.persistence.room:runtime:$room_version"
annotationProcessor "android.arch.persistence.room:compiler:$room_version"
kapt "android.arch.persistence.room:compiler:$room_version"

0 votes

Merci pour votre aide.

0 votes

@Lyofen j'ai le même problème mais l'ajout de kapt introduit quelques erreurs gradle, veuillez regarder ici. stackoverflow.com/questions/44142964/ .

0 votes

Merci beaucoup monsieur !

12voto

dharmin007 Points 634

Essayez ces étapes

Étape 1. Définissez le room_version en el project.gradle fichier

buildscript {
    ext.kotlin_version = '1.1.51'
    ext.room_version = '1.0.0-alpha9-1'
...

Étape 2. Appliquer le kotlin-kapt dans le module d'extension app.gradle et cela a résolu mon problème.

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

android {
    compileSdkVersion 26
    buildToolsVersion "26.0.1"
...

Étape 3. Ajouter le kapt dans le app.gradle fichier

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation "android.arch.persistence.room:runtime:$room_version"
    annotationProcessor "android.arch.persistence.room:compiler:$room_version"
    kapt "android.arch.persistence.room:compiler:$room_version"
...
}

4voto

Juan Acevedo Points 1015

Toute personne intéressée par l'utilisation de Kotlin avec Room et Data Binding peut voir cet exemple de projet https://github.com/entrpn/kotlin-room-databinding

1voto

j2emanue Points 3456

J'ai failli abandonner. Mais après avoir fait ce que dharmin007 a dit, j'ai aussi dû nettoyer le projet. qui l'a fait fonctionner. J'ai remarqué que chaque fois que vous ajoutez kapt à gradle, vous DEVEZ nettoyer le projet après avoir synchronisé gradle.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X