我有一个数据类:
@Parcelize
data class Task(
var task: String,
var done: Boolean = false
) : Parcelable
以及我的 Room 数据库的相应类型转换器:
object Converters {
...
@TypeConverter
fun tasksToJson(list: List<Task>): String {
val objects = list.map { item ->
val jsonObject = JSONObject()
jsonObject.put("task", item.task)
jsonObject.put("done", item.done)
}
return JSONArray(objects).toString()
}
@TypeConverter
fun jsonToTasks(json: String): List<Task> {
val iterable = JSONArray(json).iterable<JSONObject>()
return iterable.map { jsonObject ->
Task(jsonObject.getString("task"), jsonObject.getBoolean("done"))
}
}
@Suppress("UNCHECKED_CAST")
private fun <T> JSONArray.iterable(): Iterable<T> {
return Iterable {
object : Iterator<T> {
var nextIndex = 0
override fun next(): T {
val element = get(nextIndex)
nextIndex++
return element as T
}
override fun hasNext(): Boolean {
return nextIndex < length()
}
}
}
}
}
一切都很好,但我想扩展我的数据类,以便每个任务都有一个子任务。这就是我扩展数据类的方式:
@Parcelize
data class Task(
var task: String,
var done: Boolean = false,
var subTasks: List<Task> = emptyList() // -> sub tasks based on the same data class
) : Parcelable
所以问题是,我是否也需要为子任务扩展类型转换器?如果是的话,我该如何完成?
所以问题是,我是否也需要为子任务扩展类型转换器?如果是的话,我该如何完成?
答案可能是否,但这取决于相应的
@Entity
注释类。
总而言之,如果任务(无论是否包含子任务列表)未嵌入,则 TypeConverter 应该足够,因为列表是存储(转换)的任务对象的一部分。
但是,如果任务嵌入了
@Embedded
注释,那么在添加子任务列表之前,所有字段都是 Room 可以处理的类型,但之后是列表字段/成员,因为它变成了自己的列是的,需要一个 TypeConverter。
@Entity
注释的类,如果entities
注释的@Database
参数中的实体之一确定表的列。
如果需要类型转换器的对象直接是类的字段/成员,那么该字段/成员本身就是一列。如果该字段/成员不是 Room 可以直接处理的类型,那么它将需要一对 TypeConverter 函数/方法将对象转换为 Room 可以处理的类型。
例如如果你有:-
@Entity
data class TheTable(
@PrimaryKey
val id: Long?=null,
val something: String,
val task: Task
}
然后任务字段/成员相当于一个名为任务的列,它是一个对象,需要一个 TypeConverter 对来将 Task 对象转换为可以存储在 SQLite 数据库中的值。
数据库中的表将使用
CREATE TABLE IF NOT EXISTS
TheTable (
idINTEGER,
somethingTEXT NOT NULL,
task TEXT NOT NULL, PRIMARY KEY(
id))
创建。即列将是:-
类型转换器,为了简单起见,答案是无用的(数据方面)
@TypeConverter fun cnvTaskToString(task: Task): String = ""
(它将任务转换为“”)
但是,如果您有:-
@Entity
data class TheTable(
@PrimaryKey
val id: Long?=null,
val something: String,
@Embedded
val task: Task
}
然后将使用
CREATE TABLE IF NOT EXISTS
TheTable (
idINTEGER,
somethingTEXT NOT NULL,
taskTEXT NOT NULL,
done INTEGER NOT NULL, PRIMARY KEY(
id))
创建表格,即列:-
即任务对象的字段已从任务对象复制。正如给定的示例中所示,字段/成员是可以处理的类型,然后不需要 TypeConverters。
但是,如果添加了列表字段,则如下所示:-
data class Task(
var task: String,
var done: Boolean = false,
val subtasks: List<Task> = emptyList()
)
然后现有的 TypeConverter,如上所述(由于空列表默认值),可以应对。即 GSON 应该处理 JSON 字符串。 Room 关心的只是从相应的 Task 对象存储/检索字符串。
但是,如果任务是
@Embedded
,那么由于存在附加字段/成员,并且它不是 Room 可以处理的类型,因此作为 List 的子任务对象/列将需要 TypeConverter,作为子任务,由于任务被嵌入。