似乎有两种情况,通过@Bindable
分配到绑定的groovy属性不会调用侦听器:
(1)如果属性是在类本身内分配的,例如this.prop = newval
,或简称为prop = newval
(2)如果属性的值没有改变obj.prop = oldval
有解决方法吗?理想情况下,它将支持简单的(.)prop=
语法。
代码示例:
import java.beans.*
import groovy.beans.*
int changes = 0
def obj = Binding.newInstance()
obj.propertyChange = { changes++ }
obj.prop = "1st change" // change recorded
obj.twoChanges() // no changes recorded
obj.prop = obj.prop // no change recorded
assert changes == 4 // fails: changes is 1
class Binding {
@Bindable String prop
def twoChanges() {
prop = "2nd change"
this.prop = "3rd change"
}
}
答案 0 :(得分:2)
通过创建隐藏的@Bindable
属性(mprop
)并仅提供prop
的getter和setter而没有名为prop
的实际属性,我能够使用您的语法不变。除了将属性设置为相同值(检测到4个更改中的3个)之外,这适用于所有内容:
import java.beans.*
import groovy.beans.*
int changes = 0
def obj = Binding.newInstance()
obj.propertyChange = { changes++ }
obj.prop = "1st change" // change recorded
obj.twoChanges() // two changes recorded
obj.prop = obj.prop // no change recorded
assert changes == 4 // fails: changes is 3
class Binding {
@Bindable String mprop // changed from prop to mprop
def setProp(x) {setMprop(x)} // new setter
def getProp() {getMprop()} // new getter
def twoChanges() {
prop = "2nd change"
this.prop = "3rd change"
}
}
答案 1 :(得分:1)
对于(1),@Bindable
是一个AST,它生成自定义的setter,以及当你访问类中的属性时,它不会通过setter。这有效:
import java.beans.*
import groovy.beans.*
int changes = 0
def obj = Binding.newInstance()
obj.propertyChange = { changes++ }
obj.prop = "1st change" // change recorded
obj.twoChanges() // no changes recorded
obj.prop = obj.prop // no change recorded
assert changes == 3 // fails: changes is 1
class Binding {
@Bindable String prop
def twoChanges() {
setProp( "2nd change" )
this.setProp( "3rd change" )
}
}
对于(2),好像,它似乎是PropertyChangeListener
的{{3}},因为该属性未被更改。也许您可以提供standard behavior,或者只创建一个自定义设置器。
答案 2 :(得分:0)
这是我最终如何做到这一点,而不需要使用@Bindable。我愿意接受建议,尤其是this.with {}
。
class Obj {
int val = 0
static int numCalls = 0
List assigns = []
void setProperty(String name, Object value) {
this.@"$name" = value
assigns << [name: value]
numCalls ++
}
int nop() {
this.with {
val = val
}
}
int inc() {
this.with {
this.val += 1
}
return this.val
}
}
def obj = Obj.newInstance()
assert obj.val == 0 && Obj.numCalls == 0
assert obj.inc() == 1 && obj.val == 1 && Obj.numCalls == 1
assert obj.nop() == 1 && obj.val == 1 && Obj.numCalls == 2 && obj.assigns.size() == 2