How to Create Change Listener for Variable

How to create change listener for variable?

This is one of the many reasons to hide variables behind setter/getter pairs. Then, in the setter you can notify your listener that this variable has been modified in the appropriate way. As the others have commented, there is no built in way to do exactly what you want, you need to implement it yourself.

Alternatively Benjamin brings up an interesting pattern, called the Decorator pattern, which might be useful to you if the code in question cannot be modified. You can look up more info at Wikipedia

The idea is to build a compatible wrapper around an object. Lets say your object in question is of type MyClass.

class MyClass{
public void doFunc(){...}
}

class MyLoggedClass extends MyClass{
MyClass myObject;

public void doFunc(){
//Log doFunc Call
myObject.doFunc();
}
}

instead of

MyClass object = new MyClass();

You would use

MyClass object = new MyLoggedClass(new MyClass());

Now your rest of the code would use object as per normal, except that each function call will be logged, or notified, etc.

As you will see in Wikipedia, this is typically done via an interface that the class in question inherits from, but this may not be possible in your case.

How to implement an Variable Change Listener, for a variable running in different thread (example)

Myself, I'd just give my class a PropertyChangeSupport field, give it an addPropertyChangeListener(...) and removePropertyChangeListener(...) methods, only allow the atomic variable to be changed in a setXxx(...) method, and in that same method, fire a property change event. I would take care that the fire event be called on the GUI's event thread. Note that if your GUI is a Swing GUI, then if you use a SwingPropertyChangeSupport, the threading issue is taken care of for you.

For example, from my answer to a similar question here:

public class ServerManager implements Runnable {
public static final String IS_RUNNING = "is running"; // for the Event's name

// if not a Swing app, then use a PropertyChangeSupport field
private SwingPropertyChangeSupport propChngSupport = new SwingPropertyChangeSupport(this);
private volatile boolean isRunning = false;
// other variables

// addPropertyChangeListener(...) {...} goes here
// removePropertyChangeListener(...) {...} goes here

public void setIsRunning(boolean isRunning) {
boolean newValue = isRunning;
boolean oldValue = this.isRunning;
this.isRunning = isRunning;
propChngSupport.firePropertyChange(IS_RUNNING, oldValue, newValue);
}

public void run() {
// ....
}

// other methods
}

As for your specific questions:

  • Do I need to register a listener to do this or is there a simpler way?

I don't see anything difficult about registering listeners.

  • Where and how do I register the listener?

The observer would register on the observed by calling some addListenerXxx(...) type method.

  • Do I have to setup a separate interface class (I'd like to avoid this if possible).

Not if you use PropertyChangeListener or Java's Observer/Observable class/interface combination

  • Could you please some real example I could use - abstract explanations aren't helping me so far!

You need to ask more specific questions than this one.

Listen to js variable change

You can create a listener for the variable change using setTimeout, something like:

let place2IsReady = false;

setReadyListener();

// testing wait 2 seconds to set place2IsReady to true
// so: an alert should occur after 2 seconds
setTimeout(() => place2IsReady = true, 2000);

function setReadyListener() {
const readyListener = () => {
if (place2IsReady) {
return alert("Ready!");
}
return setTimeout(readyListener, 250);
};
readyListener();
}

How to watch a variable for changes

You need to replace the type int with a class which will invoke your listener whenever the values changes. You might like to ignore setting the value when it hasn't actually changed.

e.g.

 private int value;
private final MyValueChangeListener listener;

public void setValue(int value) {
if(this.value == value) return;
listener.changed(this, this.value, value);
this.value = value;
}

You can perform this replace using byte code injection, but it is much simple to change the original code.

An alternative is to monitor the value to look for changes periodically. Unless the value changes very slowly you might not see every change. You can use the Debugger API to do this but it not simple and I wouldn't suggest you use it unless you are familiar with the API already.

Java Debugger API Links

http://java.sun.com/javase/technologies/core/toolsapis/jpda/

http://docs.oracle.com/javase/6/docs/technotes/guides/jpda/

http://docs.oracle.com/javase/6/docs/jdk/api/jpda/jdi/

A listener for changing variable in android

It's not possible directly. However, you can make your field private, add getters and setters, and create a method of adding listeners (this is called the Observer pattern):

interface ConnectionBooleanChangedListener {
public void OnMyBooleanChanged();
}

public class Connect {
private static boolean myBoolean;
private static List<ConnectionBooleanChangedListener> listeners = new ArrayList<ConnectionBooleanChangedListener>();

public static boolean getMyBoolean() { return myBoolean; }

public static void setMyBoolean(boolean value) {
myBoolean = value;

for (ConnectionBooleanChangedListener l : listeners) {
l.OnMyBooleanChanged();
}
}

public static void addMyBooleanListener(ConnectionBooleanChangedListener l) {
listeners.add(l);
}
}

Then, wherever you want to listen to changes of the boolean, you can register a listener:

Connect.addMyBooleanListener(new ConnectionBooleanChangedListener() {
@Override
public void OnMyBooleanChanged() {
// do something
}
});

Adding a method to remove listeners is left as an exercise. Obviously, for this to work, you need to make sure that myBoolean is only changed via setMyBoolean, even inside of Connect.

How to set up a listener for a variable in Kotlin

You can use built-in Kotlin delegates, for example:

object SignalChange {
var refreshListListeners = ArrayList<InterfaceRefreshList>()

// fires off every time value of the property changes
var property1: String by Delegates.observable("initial value") { property, oldValue, newValue ->
// do your stuff here
refreshListListeners.forEach {
it.refreshListRequest()
}
}
}

interface InterfaceRefreshList {
fun refreshListRequest()
}

Add listeners like this:

SignalChange.refreshListListeners.add(object : InterfaceRefreshList {
override fun refreshListRequest() {
refreshList()
}
})

OR

Intead of interface you can use lambda:

object SignalChange {
var refreshListListeners = ArrayList<() -> Unit>()

// fires off every time value of the property changes
var property1: String by Delegates.observable("initial value") { property, oldValue, newValue ->
// do your stuff here
refreshListListeners.forEach {
it()
}
}
}

And to add listener just call:

SignalChange.refreshListListeners.add(::refreshList)
//or
SignalChange.refreshListListeners.add { refreshList() }

fun refreshList() {

}


Related Topics



Leave a reply



Submit