Kotlin中的动态属性访问

3

来自 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']

正如一些回答中所提到的,这可以通过反射实现。具体怎么做呢?


2
嗨,有趣,也许可以使用反射 - IronMan
我不知道你在这里使用的对象,但是有没有一种方法可以使用数组或列表——专为索引访问而设计的类型——而不是一系列单独的属性? - gidds
@gidds 是的,这个例子如果有编号的话,用数组会更好(你可以有一个资源数组吗?),但是我的问题一般来说还是存在的。 - Jonathan Tuzman
我不确定那段代码是从哪里来的,或者是否有意为之展示一个switch语句,但我只想指出更好的做法是使用一个固定的LevelListDrawable并修改它的级别。使用反射或字符串的getIdentifier方法不能在编译时提供安全性,所以通常应该避免使用。 - Pawel
resources.getIdentifier 在底层使用了反射。请注意,应避免使用反射,因为它会丢弃使用强类型语言的好处(编译器在运行代码之前就能捕获错误)。如果您一开始将可绘制对象存储在数组中,就不需要这个 when 语句。 - Tenfour04
2个回答

3
val resId = context.resources.getIdentifier("ic_sleep_${item.sleepQuality}", "drawable", context.packageName)
setImageResource(if (resId != 0) resId else R.drawable.ic_sleep_active)

通过反射(基于如何通过反射获取Java类中的public static final字段/属性值):

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是一种静态类型的编程语言,不支持“变量变量”。


3
值得指出的是,在像 Kotlin 这样的静态类型通用编程语言中,反射虽然看起来很有吸引力,但很少是一个好的解决方案。当然,在编写框架、插件、测试、编译时工具、依赖注入等时,反射是必要且非常有用的。但它会绕过类型系统和所有通常的编译时检查和优化,并且性能表现不佳。如果你发现自己需要使用反射,这通常是提示你有更好的代码结构方式。 - gidds

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接