org.bushe.swing.event.package.html Maven / Gradle / Ivy
Show all versions of nifty Show documentation
The main package, provides publish/subscribe services for Swing and non-Swing applications.
See the overview for an introduction to the EventBus' pub/sub services.
This simple example prints "Hello World" using class-based publication.
class HelloEvent {
public String getWorld() {
return "World";
}
}
class MySubscriber implements EventSubscriber {
//EventSubscriber implementation
public void onEvent(Object event) {
HelloEvent helloEvent = (HelloEvent)event;
System.out.println("Hello"+helloEvent.getWorld());
}
}
class HelloEventBus {
public static void main(String args[]) {
MySubscriber subscriber = new MySubscriber();
EventBus.subscribe(HelloEvent.class, subscriber);
EventBus.publish(new HelloEvent());
}
}
Though the term "Event Bus" refers to the entire library, the {@link org.bushe.swing.event.EventBus} class
used above is a static wrapper around a global instance of an {@link org.bushe.swing.event.EventService},
specifically the {@link org.bushe.swing.event.SwingEventService} implementation by default. MySubscriber
subscribes itself to the HelloEvent.class. When main() publishes an instance of HelloEvent the Event Bus
calls MySubscriber's onEvent method, passing the HelloEvent as a parameter, and "Hello World" is printed.
The above subscriber can be simplified by using a generic type.
class MySubscriber implements EventSubscriber {
//EventSubscriber implementation
public void onEvent(HelloEvent helloEvent) {
System.out.println("Hello"+helloEvent.getWorld());
}
}
Alternatively, this example can be coded using EventBus annotations and the AnnotationProcessor, removing some boilerplate code:
class MySubscriber {
@EventSubscriber(eventClass=HelloEvent.class)
public void printOutHelloWorld(HelloEvent event) {
System.out.println("Hello"+helloEvent.getWorld());
}
}
class HelloEventBus {
public static void main(String args[]) {
MySubscriber subscriber = new MySubscriber();
AnnotationProcessor.process(subscriber);//makes a proxy subscriber to call subscriber.printOutHelloWorld
EventBus.publish(new HelloEvent());
}
}
This second example prints "Hello World" using topic-based publication.
class MyTopicSubscriber implements EventTopicSubscriber {
//EventTopicSubscriber implementation
public void onEvent(String topic, Object event) {
System.out.println(topic+" "+event);
}
}
class HelloEventBus {
public static void main(String args[]) {
MyTopicSubscriber subscriber = new MyTopicSubscriber();
EventBus.subscribe("Hello", subscriber);
EventBus.publish("Hello", "World");
}
}
MyTopicSubscriber subscribes itself to the topic named "Hello". When main() publishes the
String "World" (the "payload") on the event topic "Hello",
the EventBus calls MyTopicSubscriber on the Swing EDT and "Hello World" is printed.
Alternatively, this example can also be coded using EventBus annotations and the AnnotationProcessor:
class MyTopicSubscriber {
@EventTopicSubscriber(topic="Hello");
public void printOutHelloWorld(String topic, Object event) {
System.out.println(topic+" "+event);
}
}
class HelloEventBus {
public static void main(String args[]) {
MySubscriber subscriber = new MySubscriber();
AnnotationProcessor.process(subscriber);//makes a subscriber to call subscriber.printOutHelloWorld
EventBus.publish("Hello", "World");
}
}
Important: The EventBus uses WeakReferences by default, so this WILL NOT WORK
since it uses an anonymous inner class:
public static void main(String args[]) {
EventBus.subscribe("Hello", new MySubscriber());
//subscriber will likely get garbage collected - no Hello World!!!
EventBus.publish("Hello", "World");
}
In the above example, the subscriber will likely be garbage collected before the publication occurs.
However you can subscribe strongly instead:
public static void main(String args[]) {
EventBus.subscribeStrongly("Hello", new MySubscriber());
//subscriber will not get garbage collected
EventBus.publish(new HelloEvent());
//In real apps use unsubscribe to make sure you don't leave a subscriber hanging
//around in the EventBus forever (a memory leak), unless you really want to
EventBus.unsubscribe(subscriber);
}
This last example shows support for generic types. In the application for this example, there are
many List's that are published. This subscriber only want to be notified of List's of Trades, or List<Trade>.
Due to type erasure, this feature requires an addition step - the use of a TypeReference object:
public class TradeSubscriber implements EventSubscriber {
public TradeSubscriber() {
TypeReference<List<Trade>> subscribingTypeReference = new TypeReference<List<Trade>>(){};
EventBus.subscribe(subscribingTypeReference.getType(), this);
}
public void onEvent(Object object) {
}
}
//Publisher
List<Trade> trades = new ArrayList<Trade>();
trades.add(trade);
TypeReference<List<Trade>> publishingTypeReference = new TypeReference<List<Trade>>(){};
EventBus.publish(publishingTypeReference.getType(), trades);
There are two EventService implementations provided by the EventBus library. One is the {@link org.bushe.swing.event.ThreadSafeEventService}.
As the name implies the ThreadSafeEventService can be used in multithreaded environments. There are no extra threads created by the EventBus,
as notification generally happens on the publishing thread. The exception to this rule is the {@link org.bushe.swing.event.SwingEventService},
which extends the ThreadSafeEventService and ensures that notifications of subscribers are later posted on the
Swing/AWT {@link java.awt.EventDispatchThread} if the publishing thread is not already the EventDispatchThread.
The key class in the EventBus library is the {@link org.bushe.swing.event.EventBus}. The EventBus is a wrapper around an EventService, by default
a SwingEventService. Non-Swing applications can change the default implementation, by using the {@link org.bushe.swing.event.EventServiceLocator}.
An application may use multiple event services. The EventServiceLocator is a central registry of EventServices where any
number of EventServices can be registered by name, but there is only one EventService instance created by the EventBus library and it registered by default
under both the names {@link org.bushe.swing.event.EventServiceLocator#SERVICE_NAME_EVENT_BUS} ("EventBus") and {@link org.bushe.swing.event.EventServiceLocator#SERVICE_NAME_SWING_EVENT_SERVICE} ("SwingEventService").
The EventBus class wraps the EventService registered under the name "EventBus". By default, the EventServiceLocator's "EventBus" defaults to the
EventService registered under the name "SwingEventService", which is an instance of a SwingEventService. So out-of-the-box there is one global event
service that should only be used for Swing apps, but this can either be changed programmatically or via Java properties before the first time the EventServices
are requested from the EventServiceLocator or the first time the EventBus us used, whichever comes first.