为什么我在构建项目时出错?

时间:2021-05-21 11:17:50

标签: android kotlin

我观看了 youtube video 并在我的项目中实现了数据库
数据库.kt:

@Database(entities = [Result::class], version = DATABASE_VERSION, exportSchema = false)
abstract class ResultDatabase : RoomDatabase() {

abstract fun resultDao(): ResultDao

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

    fun getDatabase(context: Context): ResultDatabase {
        val tempInstance = INSTANCE

        if (tempInstance != null) {
            return tempInstance
        }

        synchronized(this) {
            val instance = Room.databaseBuilder(
                context.applicationContext,
                ResultDatabase::class.java,
                TABLE_NAME
            ).build()

            INSTANCE = instance

            return instance
        }
    }
}

}

ResultClass.kt:

@Entity(tableName = TABLE_NAME)
data class Result(private val id: Int,
              private val cheatingEnabled: Boolean,
              private val cheatingSuccessful: Boolean,
              private val min: Long,
              private val max: Long,
              private val result: Long,
              private val time: LocalDateTime

)

ResultDao.kt:

@Dao
interface ResultDao {
    @Insert(onConflict = OnConflictStrategy.IGNORE)
    fun addResult(result: Result)

    @Query(value = "SELECT * FROM random_data ORDER BY id ASC")
    fun getAllResults(): LiveData<List<Result>>
}

Repo.kt

class ResultsRepository(private val resultDao: ResultDao) {
    val resultHistory: LiveData<List<Result>> = resultDao.getAllResults()

    fun addResult(result: Result) {
        resultDao.addResult(result)
    }
}

向数据库插入数据的函数:

private fun insertDataToDatabase(min: Long,
                                 max: Long,
                                 result: Long,
                                 cheatingEnabled: Boolean,
                                 cheatingSuccessful: Boolean
) {
    val time = LocalDateTime.now()
    val resultEntity = Result(0, cheatingEnabled, cheatingSuccessful, min, max, result, time)
    viewModelScope.launch {
        repository.addResult(resultEntity)
    }
}

错误:

C:\Users\Maxim\AndroidStudioProjects\AdvancedNumberGenerator\app\build\tmp\kapt3\stubs\debug\com\example\advancednumbergenerator\database\Result.java:14: error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.
private final java.time.LocalDateTime time = null;
                                      ^C:\Users\Maxim\AndroidStudioProjects\AdvancedNumberGenerator\app\build\tmp\kapt3\stubs\debug\com\example\advancednumbergenerator\database\Result.java:8: error: Cannot find getter for field.
private final int id = 0;
                  ^C:\Users\Maxim\AndroidStudioProjects\AdvancedNumberGenerator\app\build\tmp\kapt3\stubs\debug\com\example\advancednumbergenerator\database\Result.java:9: error: Cannot find getter for field.
private final boolean cheatingEnabled = false;
                      ^C:\Users\Maxim\AndroidStudioProjects\AdvancedNumberGenerator\app\build\tmp\kapt3\stubs\debug\com\example\advancednumbergenerator\database\Result.java:10: error: Cannot find getter for field.
private final boolean cheatingSuccessful = false;
                      ^C:\Users\Maxim\AndroidStudioProjects\AdvancedNumberGenerator\app\build\tmp\kapt3\stubs\debug\com\example\advancednumbergenerator\database\Result.java:11: error: Cannot find getter for field.
private final long min = 0L;
                   ^C:\Users\Maxim\AndroidStudioProjects\AdvancedNumberGenerator\app\build\tmp\kapt3\stubs\debug\com\example\advancednumbergenerator\database\Result.java:12: error: Cannot find getter for field.
private final long max = 0L;
                   ^C:\Users\Maxim\AndroidStudioProjects\AdvancedNumberGenerator\app\build\tmp\kapt3\stubs\debug\com\example\advancednumbergenerator\database\Result.java:13: error: Cannot find getter for field.
private final long result = 0L;
                   ^C:\Users\Maxim\AndroidStudioProjects\AdvancedNumberGenerator\app\build\tmp\kapt3\stubs\debug\com\example\advancednumbergenerator\database\Result.java:14: error: Cannot find getter for field.
private final java.time.LocalDateTime time = null;
                                      ^C:\Users\Maxim\AndroidStudioProjects\AdvancedNumberGenerator\app\build\tmp\kapt3\stubs\debug\com\example\advancednumbergenerator\database\Result.java:7: error: An entity must have at least 1 field annotated with @PrimaryKey

公共最终类结果{ ^C:\Users\Maxim\AndroidStudioProjects\AdvancedNumberGenerator\app\build\tmp\kapt3\stubs\debug\com\example\advancednumbergenerator\database\Result.java:14:错误:无法弄清楚如何从光标。 私有最终 java.time.LocalDateTime time = null; ^

我该如何解决这个错误?可以使用 LocalDateTime 数据类型和 Long 而不是 int 连接吗?但我什至没有开始插入,我在构建时出错。我看到了类似的问题,有人建议使用 json 对象,但是来自 youtube 的人的项目没有 json 且没有任何错误。

1 个答案:

答案 0 :(得分:1)

<块引用>

是否可以使用 LocalDateTime 数据类型和 Long 而不是 int 来连接?

是的。

<块引用>

但我什至没有开始插入,我在构建时出错

Room 使用注释处理器 — 即您添加到 kaptdependencies 语句。该注释处理器不知道如何处理 LocalDateTime。而且,它不能与 private Kotlin 属性一起使用。

<块引用>

我该如何解决这个错误?

首先从 private 上的这些属性中删除 Result 关键字。这应该将 LocalDateTime 的错误减少到 2。

然后,您需要教 Room 如何使用 LocalDateTime

为此,您需要一个带有一对 @TypeConverter 函数的类,这些函数可以在 LocalDateTime 和...之间进行转换。在 this sample 中,我有 InstantLong 之间的类型转换器:

import androidx.room.TypeConverter
import java.time.Instant

class TypeTransmogrifier {
  @TypeConverter
  fun fromInstant(date: Instant?): Long? = date?.toEpochMilli()

  @TypeConverter
  fun toInstant(millisSinceEpoch: Long?): Instant? = millisSinceEpoch?.let {
    Instant.ofEpochMilli(it)
  }
}

然后,您需要将 @TypeConverters 注释(注意尾随的 s)添加到某些内容以使用 @TypeConverter 注释注册您的类。一个简单的地方是在你的 @RoomDatabase 课上,就像我在 this sample 中所做的那样:

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

private const val DB_NAME = "stuff.db"

@Database(entities = [ToDoEntity::class], version = 1)
@TypeConverters(TypeTransmogrifier::class)
abstract class ToDoDatabase : RoomDatabase() {
  abstract fun todoStore(): ToDoEntity.Store

  companion object {
    fun newInstance(context: Context) =
      Room.databaseBuilder(context, ToDoDatabase::class.java, DB_NAME).build()
  }
}

考虑到这两点,在 my sample project 中,我的任何实体都可以使用 Instant。您会为 LocalDateTime 做同样的事情(或者,也许将您的实体从使用 LocalDateTime 切换到使用 Instant)。

您可以在 the documentation 中阅读更多相关信息。