Подтвердить что ты не робот

Реализация пространства настойчивости в Котлине

Я реализую Room Persistence lib в kotlin для реализации моей базы данных.

Ниже приведены мои классы Entity, Dao и Database:

Food.kt

@Entity
class Food(@ColumnInfo(name = "food_name") var foodName: String,
           @ColumnInfo(name = "food_desc") var foodDesc: String,
           @ColumnInfo(name = "protein") var protein: Double,
           @ColumnInfo(name = "carbs") var carbs: Double,
           @ColumnInfo(name = "fat") var fat: Double)
{
    @ColumnInfo(name = "id")
    @PrimaryKey(autoGenerate = true)
    var id: Long = 0
    @ColumnInfo(name = "calories")
    var calories: Double = 0.toDouble()
}

PersonalizedFood.kt

@Entity(primaryKeys = arrayOf("food_id","date"))
class PersonalizedFood(@ColumnInfo(name = "quantity") var quantity: Int,
                       @ColumnInfo(name = "unit") var unit: String,
                       @ColumnInfo(name = "date") var date: Date){

    @ColumnInfo(name = "food_id")
    var foodId:Long = 0
}

FoodDao.kt

@Dao
interface FoodDao {

    companion object{
        const val ID = "id"
        const val NAME = "name"
        const val PROTEIN = "protein"
        const val DESC = "desc"
        const val CARBS = "carbs"
        const val FAT = "fat"

        const val DATE = "date"
        const val FOOD_ID = "food_id"

        const val ALL_FOOD_LIST = "food"
        const val PERSONALISED_FOOD_LIST = "personalised_food"
    }

    /**
     * Returns food details of a food given by food_id
     */
    @Query("SELECT * FROM $ALL_FOOD_LIST WHERE $ID=:food_id")
    fun getFoodDetails(food_id:Long):Food

    /**
     * Inserts food items in all_food_list
     */
    @Insert
    fun addFoodList(list:ArrayList<Food>)

    @Insert(onConflict = REPLACE)
    fun saveFood(food:PersonalizedFood)

    @Query("SELECT * FROM $PERSONALISED_FOOD_LIST WHERE $FOOD_ID=:foodId and $DATE=:date")
    fun getFood(foodId:Int, data:Date):PersonalizedFood

    @Query("SELECT * FROM $ALL_FOOD_LIST where $ID in (select $FOOD_ID from $PERSONALISED_FOOD_LIST where $DATE = :date)")
    fun getFood(date:Date):ArrayList<Food>
}

Converter.kt

class Converter {

    companion object{
        @TypeConverter
        fun fromTimestamp(value: Long?): Date? {
            return if (value == null) null else Date(value)
        }

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

FoodDatabase.kt

@Database(entities = arrayOf(Food::class, PersonalizedFood::class), version = 1)
@TypeConverters(Converter::class)
abstract class FoodDatabase : RoomDatabase(){
    abstract fun foodDao():FoodDao

    companion object{
        private val databaseName = "diet"

        var dbInstance:FoodDao? = null
        fun getInstance(context:Context):FoodDao?{
            if(dbInstance == null)
                dbInstance = Room.inMemoryDatabaseBuilder(context, FoodDatabase::class.java).build().foodDao()
            return dbInstance;
        }
    }
}

И когда я запускаю следующий код для создания базы данных:

FoodDatabase.getInstance(baseContext)?.getFood(Calendar.getInstance().time)

Это дает мне следующее исключение:

Причина: java.lang.RuntimeException: не удается найти реализацию для com.chandilsachin.diettracker.database.FoodDatabase. FoodDatabase_Impl не существует в android.arch.persistence.room.Room.getGeneratedImplementation(Room.java:90) в android.arch.persistence.room.RoomDatabase $ Builder.build(RoomDatabase.java:340) в com.chandilsachin.diettracker.database.FoodDatabase $ Companion.getInstance(FoodDatabase.kt: 21) по адресу com.chandilsachin.diettracker.MainActivity $ SetUpFoodDatabase.doInBackground(MainActivity.kt: 95) по адресу com.chandilsachin.diettracker. Основная активность: 77) на android.os.AsyncTask $ 2.call(AsyncTask.java:295) на java.util.concurrent.FutureTask.run(FutureTask.java:237) на android.os.AsyncTask $ SerialExecutor $ 1.run(AsyncTask. Java: 234) в java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) в java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:588) в java.runTh..java: 818)

Кто-нибудь реализовал комнатную настойчивость в котлине?

Отредактировано Этот вопрос был помечен как дубликат этого. Хотя постановка проблемы такая же, но данное решение не решает мою проблему. Решение говорит, что я должен добавить замену annotationProcessor в kapt "android.arch.persistence.room:compiler:1.0.0-alpha1". Я сделал эти изменения, и это привело к ошибке gradle во время сборки проекта.

Информация: Задачи Gradle [: app: assemblyDebug] Предупреждение: предупреждение: Поддерживаемая исходная версия 'RELEASE_7' из процессора аннотаций 'android.arch.persistence.room.RoomProcessor' меньше чем -source '1.8' Предупреждение: предупреждение: Следующие параметры были не распознается ни одним процессором: '[kapt.kotlin.generated]'/Users/BBI-M1025/Documents/BBI/Workspace_fun/Android/диет-трекер/app/src/main/java/com/chandilsachin/diettracker/database/Ошибка Food.kt: (1, 1) При обработке аннотаций произошли некоторые ошибки. Пожалуйста, смотрите сообщения об ошибках выше. Ошибка: не удалось выполнить задачу ': app: kaptDebugKotlin'.

Ошибка компиляции. Смотрите журнал для более подробной информации. Информация: BUILD FAILED за 10 секунд. Информация: 2 ошибки. Информация: 2 предупреждения. Информация: см. Полный вывод в консоли.

Я прилагаю свой файл Gradle также:

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

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.chandilsachin.diettracker"
        minSdkVersion 16
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    compile 'com.android.support:appcompat-v7:25.0.1'
    compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha8'
    compile 'com.android.support:cardview-v7:25.0.1'
    compile 'com.android.support:recyclerview-v7:25.0.1'
    compile 'com.github.ne1c:rainbowmvp:1.2.1'
    compile "org.jetbrains.anko:anko-commons:0.10.0"

    /*annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha1"
    compile "android.arch.lifecycle:extensions:1.0.0-alpha1"
    annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha1"*/

    compile "android.arch.persistence.room:runtime:1.0.0-alpha1"
    annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha1"
    kapt "android.arch.persistence.room:compiler:1.0.0-alpha1"

    testCompile 'junit:junit:4.12'
}
repositories {
    mavenCentral()
}

Кто-нибудь сталкивался с этой проблемой?

4b9b3361

Ответ 1

После того, как я немного покрутил голову, я столкнулся с этим решением.

Это было действительно сложно, так как нет официального учебника, блога и т.д., чтобы помочь с этой проблемой на данный момент.

Мне пришлось сделать несколько попыток и пробную версию для всех комбинаций плагинов и зависимостей gradle, поскольку я знал, что что-то не так с конфигурацией gradle.

Перейдем к решению:

Мне пришлось удалить apply plugin: 'kotlin-kapt' из файла build.gradle(: module) и замените annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha1" на kapt "android.arch.persistence.room:compiler:1.0.0-alpha1".

Это конфигурация gradle для успешной компиляции кода.

Но есть еще кое-что, что нужно проверить. Вы должны инициализировать свойства вашего @Entity class в отличие от java, указанные в Room Persistence lib doc. Хотя есть установщик геттера, но не упоминается о создании конструктора с инициализацией. Поэтому мне пришлось изменить класс @Entity следующим образом:

@Entity(tableName = "all_food_list")
class Food (@ColumnInfo(name = "food_name") var foodName: String = "",
            @ColumnInfo(name = "food_desc") var foodDesc: String = "",
            @ColumnInfo(name = "protein") var protein: Double = 0.0,
            @ColumnInfo(name = "carbs") var carbs: Double = 0.0,
            @ColumnInfo(name = "fat") var fat: Double = 0.0,
            @ColumnInfo(name = "calories") var calories: Double = 0.0)
{
    @ColumnInfo(name = "id")
    @PrimaryKey(autoGenerate = true)
    var id: Long = 0
}

Теперь для TypeConverts, в отличие от java, вам нужно создать нормальную функцию, а не статические функции (объект-компаньон):

class Converters{

        @TypeConverter
        fun fromTimestamp(value: String): Calendar {
            val arr = value.split("-")
            val cal = Calendar.getInstance()
            cal.set(arr[0].toInt(), arr[1].toInt(), arr[2].toInt())
            return cal
        }

        @TypeConverter
        fun dateToTimestamp(date: Calendar): String {
            return "${date.get(Calendar.DATE)}-${date.get(Calendar.MONTH)+1}-${date.get(Calendar.YEAR)}"
        }

}

Я добавляю файл build.gradle, чтобы сделать его более понятным:

build.gradle(: проект)

buildscript {
    ext.kotlin_version = '1.1.2-4'
    ext.gradle_version_stable = '2.3.2'
    ext.gradle_version_preview = '3.0.0-alpha1'
    ext.anko_version = '0.10.0'
    repositories {
        maven { url 'https://maven.google.com' }
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0-alpha1'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        maven { url 'https://maven.google.com' }
        jcenter()
        maven { url "https://jitpack.io" }
    }
}

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

build.gradle(: модуль)

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

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.chandilsachin.diettracker"
        minSdkVersion 16
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}


dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    ...
    ...
    // room persistence dependency 
    compile "android.arch.persistence.room:runtime:1.0.0-alpha1"
    kapt "android.arch.persistence.room:compiler:1.0.0-alpha1"

    testCompile 'junit:junit:4.12'
}
repositories {
    mavenCentral()
}

Я думаю, что это все, я сделал, чтобы сделать мой код уколом.

Надеюсь, это поможет и другому.

Ответ 2

Здесь мои файлы gradle, мне не нужно было добавлять плагины thoses.

build.gradle(проект):

buildscript {
    ext.kotlin_version = '1.1.2-4'
    ext.lifecycle_version = '1.0.0-alpha1'
    ext.room_version = '1.0.0-alpha1'

    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.2'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

    }
}

build.gradle(приложение)

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

//enable anotation processing with kotlin, disabled by default
kapt {
    generateStubs = true
}


android {
/**
...
**/
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])

    //kotlin
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"

    //support
    compile 'com.android.support:appcompat-v7:25.3.1'

    //google architecture
    compile "android.arch.lifecycle:runtime:$lifecycle_version"
    compile "android.arch.lifecycle:extensions:$lifecycle_version"
    annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version"
    kapt "android.arch.lifecycle:compiler:$lifecycle_version"

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

}
repositories {
    mavenCentral()
}

Затем запустите меню build- > make project, чтобы создать класс impl. Надеюсь, что это поможет

Ответ 3

Я сделал пример, похожий на Java, и имел такую ​​же проблему, и решение заключалось в добавлении строки APT apt "android.arch.persistence.room:compiler:1.0.0-alpha1"

без применения: применить плагин: 'kotlin-kapt'. Удалите эту строку!

Вам нужно очистить проект и перестроить его перед повторным запуском и попробовать удалить существующее приложение на телефоне или на виртуальном устройстве. Надеюсь, вы поможете.

Ответ 4

У меня возникает та же проблема, когда я пытаюсь перейти с Java на Kotlin:

RuntimeException: cannot find implementation for AppDatabase. AppDatabase_Impl does not exist

Я попробовал все эти ответы в этом вопросе, ни один из них не работает, а затем я нашел статью: Учебные пособия по Kotlinlang - Платформы Android, использующие обработку аннотаций:

В Kotlin вы определяете зависимости аналогично Java, используя инструмент обработки аннотаций Kotlin (kapt) вместо annotationProcessor.

Затем я изменил build.gradle(Module: app), изменив весь annotationProcessor на kapt, он работает:

--- a/app/build.gradle
+++ b/app/build.gradle
@@ -2,6 +2,8 @@ apply plugin: 'com.android.application'

 apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-kapt'
 apply plugin: 'kotlin-android-extensions'

 android {
     // Butter Knife
     implementation "com.jakewharton:butterknife:$butterknife_version"
-    annotationProcessor "com.jakewharton:butterknife-compiler:$butterknife_version"
+    kapt "com.jakewharton:butterknife-compiler:$butterknife_version"

     // Room
     implementation "android.arch.persistence.room:runtime:$arch_lifecycle_version"
-    annotationProcessor "android.arch.persistence.room:compiler:$arch_lifecycle_version"
+    kapt "android.arch.persistence.room:compiler:$arch_lifecycle_version"
     // LifeCycle
     implementation "android.arch.lifecycle:runtime:$arch_lifecycle_version"
     implementation "android.arch.lifecycle:extensions:$arch_lifecycle_version"
     implementation "android.arch.lifecycle:common-java8:$arch_lifecycle_version"
-    annotationProcessor "android.arch.lifecycle:compiler:$arch_lifecycle_version"
+    kapt "android.arch.lifecycle:compiler:$arch_lifecycle_version"

     // Dagger
     implementation "com.google.dagger:dagger:$dagger_version"
     implementation "com.google.dagger:dagger-android-support:$dagger_version"
-    annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
-    annotationProcessor "com.google.dagger:dagger-android-processor:$dagger_version"
+    kapt "com.google.dagger:dagger-compiler:$dagger_version"
+    kapt "com.google.dagger:dagger-android-processor:$dagger_version"
}

Если вы используете Butter Knife, вам также следует перейти на kapt, иначе вводимые виды могут быть нулевыми.

Ответ 5

В моем случае ситуация была немного иной. Я использовал AS 3.0.0-beta6. Kotlin - 1.1.4-3 и 1.1.50 и Room 1.0.0-alpha9-1. И поскольку я использовал gradle 3.0.0, я изменил всю свою конфигурацию на реализацию вместо компиляции. Это вызвало проблему, описанную в вопросе. Решение

Заменить   implementation "android.arch.persistence.room:runtime:1.0.0-alpha9-1"

с compile "android.arch.persistence.room:runtime:1.0.0-alpha9-1"

Совет

Используйте java для своих DAO, так как в редакторе лучше выделить.