首页 > 解决方案 > 如何为android房间上的实体插入自定义逻辑验证

问题描述

我有一个这样的实体:

data class Person(
    @PrimaryKey(autoGenerate = true) val id: Long = 0,
    @ColumnInfo(name = "user_id", index = true) var userId: Long = 0,
    @ColumnInfo(name = "first_name") var firstName: String = "",
    @ColumnInfo(name = "mid_name") var midName: String = "",
    @ColumnInfo(name = "last_name") var lastName: String = ""
) {
    public fun fullName(): String {
        return "$firstName $midName $lastName"
    }
}

我知道我可以为每个命名属性设置一个“非空”属性。但在我的情况下,不需要填写所有名称属性,我只想在此实体保存到房间数据库之前验证全名是否为空。

我正在练习使用 MVVM 框架,但现在我不确定应该将验证放在哪里。活动/片段?视图模型?存储库?还是直接在实体内部?

我想也许我应该在存储库中执行此操作,以便在将其保存到数据库之前防止输入错误。但是如果有另一个用例我需要在不同的存储库中验证相同的东西怎么办?如果是这样,那么代码将在两个存储库中复制。

我以前在 Rails 上写过 ruby​​,模型中有验证功能,例如:

# This is ruby on rails code
validate :name_validation

def name_validation
    if first_name == "" && mid_name == "" && last_name == ""
        errors.add(:name, "the name should not be totally blank")
    end
end

我想知道是否有类似的方法来验证实体中的属性,或者有什么更好的做法来解决这个问题?

请帮我弄清楚。

标签: androidvalidationkotlinandroid-room

解决方案


我想也许我们可以直接使用一个fullName属性,让它不为空。

然后制作一个Name 类进行名称处理,以及NameConveter 类进行转换。

所以示例代码可能看起来像这样:

class Name(
    var firstName: String = "",
    var midName: String = "",
    var lastName: String = ""
) {
    public fun fullName(): String {
        return "$firstName $midName $lastName".trim()
    }
}

@Entity
data class Person(
    @PrimaryKey(autoGenerate = true) val id: Long = 0,
    @ColumnInfo(name = "user_id", index = true) var userId: Long = 0,
    @ColumnInfo(name = "full_name") var fullName: Name
)

class NameStringConverter {
    @TypeConverter
    fun fromString(value: String): Name {
        val nameStr = value.split(" ")
        return Name(nameStr[0], nameStr[1], nameStr[2])
    }

    @TypeConverter
    fun nameToString(name: Name): String? {
        val fullName = name.fullName()
        // Here is the trick 
        // to make a blank full name become an invalid name for a not null property
        if (name.isNullOrBlank()) {
            return null
        } else {
            return fullName
        }
    }
}

这样我们就可以通过Name Class访问多个名称,并且数据库现在将帮助我们检查全名。

我知道我的示例代码可能会导致一些问题,例如名称字符串中的额外空白字符,但现在让我们专注于 fullName 验证问题。

我今天想出了这个解决方案,我不确定它是否是一个好的答案。

我在这里发帖,供大家评判。


推荐阅读