Estoy usando un framework llamado Processing que es básicamente un applet de Java. Tiene la capacidad de hacer eventos clave porque Applet puede. También puede pasar sus propias devoluciones de llamada al padre. No estoy haciendo eso ahora y tal vez esa es la solución. Por ahora, estoy buscando una solución más POJO. Entonces escribí algunos ejemplos para ilustrar mi pregunta.Viendo una variable para cambios sin sondeo
Ignore el uso de eventos clave en la línea de comandos (consola). Sin duda, esta sería una solución muy limpia, pero no es posible en la línea de comandos y mi aplicación real no es una aplicación de línea de comandos. De hecho, un evento clave sería una buena solución para mí, pero estoy tratando de comprender los eventos y las encuestas más allá de los problemas específicos del teclado.
Ambos ejemplos dan la vuelta a un booleano. Cuando el booleano se voltea, quiero disparar algo una vez. Podría envolver el booleano en un Objeto así que si el Objeto cambia, podría disparar un evento también. Simplemente no quiero sondear con una declaración if() innecesariamente.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/*
* Example of checking a variable for changes.
* Uses dumb if() and polls continuously.
*/
public class NotAvoidingPolling {
public static void main(String[] args) {
boolean typedA = false;
String input = "";
System.out.println("Type 'a' please.");
while (true) {
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
try {
input = br.readLine();
} catch (IOException ioException) {
System.out.println("IO Error.");
System.exit(1);
}
// contrived state change logic
if (input.equals("a")) {
typedA = true;
} else {
typedA = false;
}
// problem: this is polling.
if (typedA) System.out.println("Typed 'a'.");
}
}
}
Al ejecutar este salidas:
Type 'a' please.
a
Typed 'a'.
En algunos foros la gente sugirió el uso de un observador. Y aunque esto desacopla el controlador de eventos de la clase que se observa, todavía tengo un if() en un bucle para siempre.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Observable;
import java.util.Observer;
/*
* Example of checking a variable for changes.
* This uses an observer to decouple the handler feedback
* out of the main() but still is polling.
*/
public class ObserverStillPolling {
boolean typedA = false;
public static void main(String[] args) {
// this
ObserverStillPolling o = new ObserverStillPolling();
final MyEvent myEvent = new MyEvent(o);
final MyHandler myHandler = new MyHandler();
myEvent.addObserver(myHandler); // subscribe
// watch for event forever
Thread thread = new Thread(myEvent);
thread.start();
System.out.println("Type 'a' please.");
String input = "";
while (true) {
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
try {
input = br.readLine();
} catch (IOException ioException) {
System.out.println("IO Error.");
System.exit(1);
}
// contrived state change logic
// but it's decoupled now because there's no handler here.
if (input.equals("a")) {
o.typedA = true;
}
}
}
}
class MyEvent extends Observable implements Runnable {
// boolean typedA;
ObserverStillPolling o;
public MyEvent(ObserverStillPolling o) {
this.o = o;
}
public void run() {
// watch the main forever
while (true) {
// event fire
if (this.o.typedA) {
setChanged();
// in reality, you'd pass something more useful
notifyObservers("You just typed 'a'.");
// reset
this.o.typedA = false;
}
}
}
}
class MyHandler implements Observer {
public void update(Observable obj, Object arg) {
// handle event
if (arg instanceof String) {
System.out.println("We received:" + (String) arg);
}
}
}
La ejecución de este salidas:
Type 'a' please.
a
We received:You just typed 'a'.
Estaría bien si el if() fue un NOOP en la CPU. Pero en realidad está comparando cada pase. Veo la carga real de la CPU. Esto es tan malo como una encuesta. Tal vez pueda acelerarlo con un sueño o comparar el tiempo transcurrido desde la última actualización, pero esto no se basa en eventos. Es solo menos encuestas. Entonces, ¿cómo puedo hacer esto de manera más inteligente? ¿Cómo puedo ver un POJO para ver los cambios sin votación?
En C# parece que hay algo interesante llamado propiedades. No soy un chico C#, así que quizás esto no sea tan mágico como creo.
private void SendPropertyChanging(string property)
{
if (this.PropertyChanging != null) {
this.PropertyChanging(this, new PropertyChangingEventArgs(property));
}
}
Nota: Observable/Observer es como el manejo de eventos. Este es un patrón de controlador/observador de eventos híbrido, que es muy fácil de usar. Se puede mejorar aún más, de modo que el "firePropertyChanged" utiliza la reflexión para modificar el campo privado. Entonces todos los métodos setter son muy limpios y mantenibles, aunque el rendimiento puede disminuir. – Pindatjuh