Реализация пространства настойчивости в Котлине
Я реализую 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()
}
Кто-нибудь сталкивался с этой проблемой?
Ответы
Ответ 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, так как в редакторе лучше выделить.