【问题标题】:Dynamic property access in KotlinKotlin 中的动态属性访问
【发布时间】:2020-11-21 14:05:22
【问题描述】:

在 Kotlin 基础课程中,我们有以下代码:

@BindingAdapter("sleepImage")
fun ImageView.setSleepImage(item: SleepNight?) {
    item?.let {
        setImageResource(when (item.sleepQuality) {
            0 -> R.drawable.ic_sleep_0
            1 -> R.drawable.ic_sleep_1
            2 -> R.drawable.ic_sleep_2
            3 -> R.drawable.ic_sleep_3
            4 -> R.drawable.ic_sleep_4
            5 -> R.drawable.ic_sleep_5
            else -> R.drawable.ic_sleep_active
        })
    }
}

在其他语言中,我会通过使用 sleepQuality 整数来查找匹配元素来简化这一点,例如在 Typescript 中:

setImageResource(R.drawable[`ic_sleep_${item.sleepQuality}`] ?? R.drawable.ic_sleep_active)

要开始尝试这个,即使我的第一步没有编译:

0 -> R.drawable["ic_sleep_0"] // doesn't compile

这种操作在 Kotlin 中是否可行?

编辑/更新

这里有一些很好的回应。

对于这个特定的用例,我可以按字符串查找资源,类似于我正在尝试的:

val resId = context.resources.getIdentifier("ic_sleep_${item.sleepQuality}", "drawable", context.packageName)

但是,这不是一个通用的解决方案。以下方法不起作用:

val x = item['sleepQuality']

正如某些回复中所指出的,这可以通过反射来实现。这将如何实现?

【问题讨论】:

  • 嗨,有趣,也许用reflection
  • 我不知道您在这里使用的对象,但有没有一种方法可以使用数组或列表——类型 设计 用于索引访问——而不是一系列单独的属性?
  • @gidds 是的,这个例子,被编号,作为一个数组会更好(你能有一个资源数组吗?)但我的问题,一般来说,仍然存在。
  • 我不确定该代码来自哪里,或者它是否是为了展示开关而编写的,但我只是指出使用固定的 @ 会更干净987654328@ 并修改其级别。通过字符串使用反射或getIdentifier 的解决方案不提供编译时安全性,因此通常应避免使用它们。
  • resources.getIdentifier 在后台使用反射。请注意,应该避免使用反射,因为它放弃了使用强类型语言的好处(编译器甚至在您运行代码之前就捕获了您的错误)。如果您首先将可绘制对象存储在数组中,则不需要此 when 语句。

标签: kotlin


【解决方案1】:
val resId = context.resources.getIdentifier("ic_sleep_${item.sleepQuality}", "drawable", context.packageName)
setImageResource(if (resId != 0) resId else R.drawable.ic_sleep_active)

通过反射(基于Getting value of public static final field/property of a class in Java via reflection):

val resId = try {
    R.string::class.java.getField("ic_sleep_${item.sleepQuality}").getInt(null)
} catch (e: Exception) {
    R.string.ic_sleep_active
}
setImageResource(resId)

【讨论】:

    【解决方案2】:

    仅使用反射。 Kotlin 静态类型编程语言,不支持“变量”

    【讨论】:

    • 另外值得指出的是,虽然它看起来很有吸引力,但反射很少是像 Kotlin 这样的静态类型语言中的通用编程的好解决方案。当然,在编写框架、插件、测试、编译时工具、依赖注入等时,它可能是必要且非常有用的。但它绕过了类型系统和所有常见的编译时检查和优化,并且性能很差。如果您发现自己正在尝试使用它,这通常暗示有更好的方式来构建您的代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-12
    • 1970-01-01
    • 1970-01-01
    • 2013-07-12
    • 2015-09-02
    • 2016-04-10
    相关资源
    最近更新 更多