【问题标题】:Kotlin's data class, Android Room and custom setterKotlin 数据类、Android Room 和自定义设置器
【发布时间】:2017-12-10 16:56:08
【问题描述】:

我得到了一个看起来像这样的 Android Room 实体。到目前为止,不用担心。

@Entity(tableName = "users",
        indices = arrayOf(Index(value = "nickName", unique = true)))
data class User(@ColumnInfo(name = "nickName") var nickName: String,
                @ColumnInfo(name = "password") var password: String) {

    @ColumnInfo(name = "id")
    @PrimaryKey(autoGenerate = true)
    var id: Long = 0
}

现在我需要加密密码。使用 Java,只需使用 setter 即可完成此操作。

您将如何使用 Kotlin 来做到这一点。我找不到将 Android Room、自定义设置器和数据类结合起来的解决方案。

【问题讨论】:

  • 为什么不能覆盖值的设置器?
  • 您的问题不清楚。 “使用 Java,只需使用 setter 即可完成此操作,这样就可以了。” - Kotlin 的可变属性有什么问题?
  • @Egor 你如何为数据类做到这一点?通过私人_password 字段?在这种情况下,你在哪里连接@ColumnInfo?
  • @VincentMimoun-Prat 我想从设计的角度来看,在 setter 方法中编码密码不是正确的方法,只需在外部编码然后传递给模型
  • 您可能有兴趣知道最佳做法是不存储密码,而是存储密码的盐和散列。例如见jasypt.org/howtoencryptuserpasswords.html

标签: android kotlin android-room


【解决方案1】:

你可以试试这样的:

@Entity(tableName = "users",
        indices = arrayOf(Index(value = "nickName", unique = true)))
data class User(@ColumnInfo(name = "nickName") var nickName: String,
                private var _password: String) {

    @ColumnInfo(name = "id")
    @PrimaryKey(autoGenerate = true)
    var id: Long = 0

    @ColumnInfo(name = "password")
    var password: String = _password
        set(value) {
            field = "encrypted"
        }

    override fun toString(): String {
        return "User(id=$id, nickName='$nickName', password='$password')"
    }

}

但我不建议在 Entity 中加密密码或以某种方式修改密码,因为这不是它的责任,而且你可能会遇到密码双重加密的错误,因为当你从数据库中检索实体时,Room 会用数据填充实体这将导致加密已经加密的数据。

【讨论】:

  • 这会解决问题,但现在表中必须有两列,“_password”和“password”。我还尝试用@Ignore 注释“_password”,但 ROOM 无法编译。有什么建议吗?
  • @DariushMalek,正如我在答案中所写 - 我不推荐这种方法,最好对数据类的数据进行任何操作,仅将其用作获取和设置的容器数据。
【解决方案2】:
    @Entity(tableName = "users",
            indices = arrayOf(Index(value = "nickName", unique = true)))
    data class User(@ColumnInfo(name = "nickName") var nickName: String,
                    @ColumnInfo(name = "password") var password: String) {
    var _password = password
        set(value): String{
           //encrypt password
        }
        @ColumnInfo(name = "id")
        @PrimaryKey(autoGenerate = true)
        var id: Long = 0
    }

这将创建一个自定义设置器,因此每次设置密码时,您都可以在设置器内对其进行加密。

【讨论】:

  • 甚至没有编译
  • 导致IDE编译错误:“overload resolution ambiguous”
  • Getter 和 setter 可以在数据类中调用自定义,但您必须为它创建一个新变量。所以变量“密码”需要被称为别的东西。例如_密码
猜你喜欢
  • 2018-03-21
  • 1970-01-01
  • 1970-01-01
  • 2017-10-19
  • 1970-01-01
  • 2018-07-25
  • 1970-01-01
  • 2021-12-17
  • 2021-11-18
相关资源
最近更新 更多