获取一个ObservableValue的所有注册监听器

 2023-02-17    425  

问题描述

如何使所有听众获得可观察的价值?我可以扩展类和覆盖addListener和removeListener方法将它们存储在集合中的方法.但是该集合应该已经以某种方式存储在可观察值的内部.我怎么能得到那套?

推荐答案

我找到了解决方案的方法,您无法直接访问”听众列表希望这足够清楚)
在此处输入图像描述

另一种方式:(你是一个聪明的人,你会知道如何适应你的案件)

//SimpleFloatProperty we want to find its Listeners
    FloatPropertyBase f=ampPS.currentProperty();
    Object value;
    ChangeListener[] list;
    ChangeListener changeListener=null;
    Field field = null;
    try {
        field = FloatPropertyBase.class.getDeclaredField("helper");
        field.setAccessible(true);
        value = field.get(f);
        try {
            field = value.getClass().getDeclaredField("listener");
            field.setAccessible(true);
            changeListener =(WeakChangeListener)field.get(value);
        }catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        try {
            field = value.getClass().getDeclaredField("changeListeners");
            field.setAccessible(true);
            list =(ChangeListener[])field.get(value);
        }catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }

结果:

(请注意1个听众或大于1的差异)​​

我正在为几种类型的值添加示例

public static ChangeListener[] getChangeListeners(ObservableValue observableValue){

    Object value;
    ChangeListener[] list=null;
    ChangeListener changeListener=null;
    Field field = null;

    try {
        if(observableValue instanceof SimpleFloatProperty ){
            field = FloatPropertyBase.class.getDeclaredField("helper");
        }
        else if(observableValue instanceof SimpleBooleanProperty ){
            field = BooleanPropertyBase.class.getDeclaredField("helper");
        }
        else if(observableValue instanceof SimpleIntegerProperty ){
            field = IntegerPropertyBase.class.getDeclaredField("helper");
        }
        field.setAccessible(true);
        value = field.get(observableValue);
        try {
            field = value.getClass().getDeclaredField("listener");
            field.setAccessible(true);
            changeListener =(ChangeListener)field.get(value);
        }catch (NoSuchFieldException e) {
            //e.printStackTrace();
        }
        try {
            field = value.getClass().getDeclaredField("changeListeners");
            field.setAccessible(true);
            list =(ChangeListener[])field.get(value);
        }catch (NoSuchFieldException e) {
            //e.printStackTrace();
        }
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    if(list!=null){
        return list;
    }
    else {
        ChangeListener[] changeListeners = new  ChangeListener[1];
        changeListeners[0]=changeListener;
        return changeListeners;
    }
}

我称之为:

SimpleBooleanProperty booleanProperty = new SimpleBooleanProperty(true);
    SimpleFloatProperty simpleFloatProperty = new SimpleFloatProperty(0);
    SimpleIntegerProperty simpleIntegerProperty = new SimpleIntegerProperty(1);
    booleanProperty.addListener(changeListener);
    simpleFloatProperty.addListener(changeListener);
    simpleIntegerProperty.addListener(changeListener);
    simpleIntegerProperty.addListener(changeListener);
    System.out.println(getChangeListeners(booleanProperty).length);
    System.out.println(getChangeListeners(simpleFloatProperty).length);
    System.out.println(getChangeListeners(simpleIntegerProperty).length);

结果: 在此处输入图像说明

所以我确实得到了警告,但是工作完成了!

其他推荐答案

ObservableValue.removeListener状态的文档:

如果以前没有注册给定的侦听器(即从未添加),则此方法调用是一个no-op.

如果要避免反射,这会留下一些选择.

首先,在添加侦听器之前致电removeListener,例如:

final var property = someProperty();
final var listener = getListener();
property.removeListener( listener );
property.addListener( listener );

此技术等同于使用Set,提供的getListener()始终返回相同的对象引用. (如果同一类Override equals返回true的不同对象引用,则此也可以使用.

不利的一面是必须对添加的侦听器进行引用,这可能需要新类,但至少需要一个新的实例变量.

第二,保留一张注册听众的地图,效果:

final HashMap<ObservableValue<?>, Object> map = new HashMap<>();
final var property = someProperty();
final var listener = getListener();
map.computeIfAbsent( property, p -> {
  property.addListener( listener );
  return property;
});

尽管问题是在寻找听众列表,但我怀疑问题的目的是避免添加重复的听众,这是一个常见的情况.

以上所述是小编给大家介绍的获取一个ObservableValue的所有注册监听器,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对77isp云服务器技术网的支持!

原文链接:https://77isp.com/post/34144.html

=========================================

https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。