Android Room无法识别TypeConverer for List

时间:2018-03-19 08:43:17

标签: android kotlin android-room

这是我的实体:

@Entity(tableName = "commits")
data class Commit(
        @PrimaryKey
        @ColumnInfo(name = "hash")
        val hash: String,
        @ColumnInfo(name = "changes", typeAffinity = ColumnInfo.BLOB)
        var changes: List<DbChange>
)

以下是转换器:

class Converters {
    companion object {
        @JvmStatic
        @TypeConverter
        fun changesToByteArray(changes: List<DbChange>): ByteArray {
            ...
        }

        @JvmStatic
        @TypeConverter
        fun byteArrayToChanges(bytes: ByteArray): List<DbChange> {
            ...
        }
    }
}

我已经将转换器类添加到注释中:

@Database(entities = [Commit::class], version = 1)
@TypeConverters(Converters::class)
abstract class AppRoomDatabase : RoomDatabase() {
    ...
}

但是编译器仍然抱怨:

e: /home/perqin/workspaces/cent-budget/cent-budget/app/build/tmp/kapt3/stubs/eaDebug/com/perqin/centbudget/data/sync/commit/Commit.java:20: error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.
    private java.util.List<? extends com.perqin.centbudget.data.sync.changes.DbChange> changes;

如何解决这个问题?我完全没有想法......

1 个答案:

答案 0 :(得分:1)

这实际上是Kotlin的错,而不是Room的 正如您在错误消息中看到的那样,List<? extends DbChange>字段为List<DbChange>而不是changes,因此Room试图为TypeConverters和{{1}找到byte[] -> List<? extends DbChange>但是没有这样做。

因为List<? extends DbChange> -> byte[]方法参数类型生成为changesToByteArray类型的List<? extends DbChange>方法仍为byteArrayToChanges,因此,您会收到编译错误。

如果您想了解更多信息,我会推荐this文章。

解决方案1:
使用@JvmSuppressWildcards
注释List<DbChange>类,以便为Commit字段和它的setter生成不带通配符的类型:

charles

出于同样的原因注释@Entity(tableName = "commits") @JvmSuppressWildcards data class Commit( @PrimaryKey @ColumnInfo(name = "hash") val hash: String, @ColumnInfo(name = "changes", typeAffinity = ColumnInfo.BLOB) var changes: List<DbChange> ) 的类型:

List

解决方案2:
为列表创建包装类,如:

class Converters {
    companion object {
        @JvmStatic
        @TypeConverter
        fun changesToByteArray(changes: List<@JvmSuppressWildcards DbChange>): ByteArray {
            ...
        }

        @JvmStatic
        @TypeConverter
        fun byteArrayToChanges(bytes: ByteArray): List<DbChange> {
            ...
        }
    }
}

然后更新data class DbChanges(val list: List<DbChange>) 类:

Commit

并撰写新的@Entity(tableName = "commits") data class Commit( @PrimaryKey @ColumnInfo(name = "hash") val hash: String, @ColumnInfo(name = "changes", typeAffinity = ColumnInfo.BLOB) var changes: DbChanges )

TypeConverters