lambda 中的变量是不可变的,it 是变量bitmap 的浅拷贝。
您应该使用field 分配到支持字段(实际变量)。
set(value) {
value?.let { field = it }
}
let 函数创建变量的浅表副本,因此如果可见可变变量 (var) 被另一个线程更改,则可以安全地使用它而不会冒突变的风险。
例子:
class Test {
var prop: Int? = 5
}
fun main() {
val test = Test()
thread {
Thread.sleep(100)
test.prop = null
}
if (test.prop != null) {
Thread.sleep(300) // pretend we did something
println(test.prop) // prints null even inside if check
}
}
为了解决这些情况,使用了浅拷贝,例如 let,它传递了这些不可变的浅拷贝。
class Test {
var prop: Int? = 5
}
fun main() {
val test = Test()
thread {
Thread.sleep(100)
test.prop = null
}
test.prop?.let { // `it` is a shallow copy, changes won't be reflected
Thread.sleep(300) // pretend we did something
println(it) // prints 5
}
}
结论:it 本身并不是实际变量,因此即使您可以将某些内容分配给 it,更改也不会反映到实际变量中。
编辑:扩展属性不能有支持字段,扩展实际上是 getter 和 setter。
- 您可以做的一件事是制作一个带有唯一标识符的 Map,您可以在其中存储值,但可能无法进行垃圾回收
- 您可以做的另一件事(我推荐)是使用委托
委托示例:
class ElementBitmapDelegate {
private var value: Bitmap? = null
operator fun getValue(thisRef: Any?, property: KProperty<*>): Bitmap {
return value ?: downloadImg(PLACE_HOLDER_URL).also { setValue(thisRef, property, it) }
// return value or if value is null return from downloadImg() and set it to value
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, v: Bitmap?) {
v?.let { value = it } // if v is not null then set value to v
}
}
var Element.bitmap: Bitmap? by ElementBitmapDelegate()