Kotlin代表与房间持久性库

Sim*_*ler 5 android delegates kotlin android-room

我目前正在使用Kotlin开发一个新的android应用。我尝试实现Room来进行数据存储,但没有与Kotlin代表一起使用。

我创建了一个Identifier委托,以确保初始化后ID不变。委托看起来像这样:

class Identifier: ReadWriteProperty<Any?, Long> {

    private var currentValue = -1L

    override fun getValue(thisRef: Any?, property: KProperty<*>): Long {
        if (currentValue == -1L) throw IllegalStateException("${property.name} is not initialized.")
        return currentValue
    }

    override fun setValue(thisRef: Any?, property KProperty<*>, value: Long) {
        if (currentValue != -1L) throw IllegalStateException("${property.name} can not be changed.")
        currentValue = value
    }
}
Run Code Online (Sandbox Code Playgroud)

我的实体类如下所示:

@Entity
class Sample {

    @delegate:PrimaryKey(autoGenerate = true)
    var id by Identifier()
}
Run Code Online (Sandbox Code Playgroud)

当我尝试启动应用程序时,kapt提示我以下错误消息:

Cannot figure out how to save this field into database. You can consider adding a type converter for it.
private final com.myapp.persistence.delegates.Identifier id$delegate = null;
Run Code Online (Sandbox Code Playgroud)

我能以某种方式使它工作而不用TypeConverter为每个代表写一个吗?

use*_*613 17

使用@delegate:Ignore.

我的实体对象和... by lazy属性也有类似的问题。

例如:

var name: String = "Alice"

val greeting: String by lazy { "Hi $name" }
Run Code Online (Sandbox Code Playgroud)

这里的问题是 Room“无法弄清楚如何将此字段保存到数据库中”。我尝试添加“@Ignore”,但收到一条 lint 消息,提示“此注释不适用于目标‘带委托的成员属性’。”

事实证明,在这种情况下正确的注释是@delegate:Ignore.

解决方案:

var name: String = "Alice"

@delegate:Ignore
val greeting: String by lazy { "Hi $name" }
Run Code Online (Sandbox Code Playgroud)


Mic*_*ran 2

不幸的是,没有 - Room默认情况下为实体中定义的每个字段创建一列,当我们使用时,delegate我们会得到如下生成的代码:

   @PrimaryKey(autoGenerate = true)
   @NotNull
   private final Identifier id$delegate = new Identifier();

   public final long getId() {
      return this.id$delegate.getValue(this, $$delegatedProperties[0]);
   }

   public final void setId(long var1) {
      this.id$delegate.setValue(this, $$delegatedProperties[0], var1);
   }
Run Code Online (Sandbox Code Playgroud)

这就是为什么 Room 尝试为Identifier id$delegate.

但是,如果您只是想确保id在对象初始化后不发生更改,则根本不需要委托,只需将变量标记为final并将其放置在构造函数中,例如:

@Entity
data class Sample(
    @PrimaryKey(autoGenerate = true)
    val id: Long
)
Run Code Online (Sandbox Code Playgroud)