Interface EventQueue<T extends Event>
-
- All Known Implementing Classes:
DesktopEventQueue
,GroupEventQueue
,ServerPushEventQueue
public interface EventQueue<T extends Event>
An event queue. An event queue is a many-to-many 'channel' to publish events and to subscribe event listeners (EventListener
).Asynchronous and Synchronous Event Listeners
There are two kinds of event listeners: synchronous and asynchronous. A synchronous listener works the same as a normal event listener (listeners registered to a component (
Component.addEventListener(int, java.lang.String, org.zkoss.zk.ui.event.EventListener<? extends org.zkoss.zk.ui.event.Event>)
). It is executed one-by-one. No two event listeners belonging to the same desktop will be executed at the same time. In additions, it is invoked under an execution (i.e.,Executions.getCurrent()
never null). It is allowed to manipulate the components belonging to the current execution.On the other hand, an asynchronous listener is executed asynchronously in another thread. It can not access the components belonging to any desktop. There is no current execution (
Executions.getCurrent()
is null}. However, it is useful to make the application more responsive when executing a long operation. A typical use is to execute the long operation in an asynchronous listener, and then all other events can be processed concurrently.- Since:
- 5.0.0
- Author:
- tomyeh
-
-
Method Summary
All Methods Instance Methods Abstract Methods Modifier and Type Method Description void
close()
Closes the event queue.boolean
isClose()
Returns whether it is closed.boolean
isSubscribed(EventListener<T> listener)
Returns if an event listener is subscribed.void
publish(T event)
Publishes an event to the queue.void
subscribe(EventListener<T> listener)
Subscribes a listener to this queue.void
subscribe(EventListener<T> listener, boolean async)
Subscribes a synchronous or asynchronous listener to this event queue.void
subscribe(EventListener<T> listener, EventListener<T> callback)
Subscribes a synchronous or asynchronous listener to this event queue.boolean
unsubscribe(EventListener<T> listener)
Unsubscribes a listener from the queue.
-
-
-
Method Detail
-
publish
void publish(T event)
Publishes an event to the queue.If the scope of a event queue is desktop or group, this method must be called within an activated execution (i.e.,
Executions.getCurrent()
not null), or in an asynchronous listener (seeEventQueue
).On the other hand, if the scope is session or application, it is OK to be called without the current execution.
- Parameters:
event
- the event to publish.
Notice that all subscribers will receive the event no matter what the event's name and target are.
You could publish an anonymous event bypublish(new Event("", null, data))
.- Throws:
java.lang.IllegalStateException
- if this method is called not within an activated execution (such as a working thread), and this is a (EventQueues.DESKTOP
) orEventQueues.GROUP
event queue.
-
subscribe
void subscribe(EventListener<T> listener)
Subscribes a listener to this queue. It is the same assubscribe(listener, false)
(subscribe(EventListener,boolean)
. In other words, it subscribes a synchronous listener.Note: this method must be called within an activated execution (i.e.,
Executions.getCurrent()
not null), no matter what scope the event queue is.Note: the listener could access the component associated with the event (
Event.getTarget()
), only if this is anEventQueues.DESKTOP
event queue.An event listener can be subscribed multiple times, and it will be invoked multiple times if an event is published.
Even if this is a
EventQueues.GROUP
,EventQueues.SESSION
, orEventQueues.APPLICATION
event queue, the listener is subscribed for the current desktop only, i.e., it can only access the components belong to the subscribed desktop. If you want to use the same listener to manipulate multiple desktops, you have to subscribe them separately when the corresponding execution is available.
-
subscribe
void subscribe(EventListener<T> listener, EventListener<T> callback)
Subscribes a synchronous or asynchronous listener to this event queue. A synchronous listener works the same as a normal event listener, while an asynchronous listener is executed asynchronously in an working thread. Refer here for details.Here is an example,
<window title="long operation" border="normal"> <zscript> void print(String msg) { new Label(msg).setParent(inf); } </zscript> <button label="async long op"> <attribute name="onClick"><![CDATA[ if (EventQueues.exists("longop")) { print("It is busy. Please wait"); return; //busy } EventQueue eq = EventQueues.lookup("longop"); //create a queue String result; //subscribe async listener to handle long operation eq.subscribe(new EventListener() { public void onEvent(Event evt) { //asynchronous org.zkoss.lang.Threads.sleep(3000); //simulate a long operation result = "success"; //store the result } }, new EventListener() { //callback public void onEvent(Event evt) { print(result); //show the result to the browser EventQueues.remove("longop"); } }); print("Wait for 3 seconds"); eq.publish(new Event("whatever")); //kick off the long operation ]]></attribute> </button> <vbox id="inf"/> </window>
Notice that, though an asynchronous listener cannot access the desktop and has no current execution, it can invoke
publish(T)
to publish the events. Refer to another example insubscribe(EventListener,boolean)
.- Parameters:
listener
- the asynchronous listener to invoke when an event is receivedcallback
- the callback listener, which will be invoked if the asynchronous listen has been invoked. Unlike the asynchronous listener, the callback listener works like a normal listener. You can access the current execution, and update the desktop.
Version Difference: since 5.0.8, the event argument is the same as the one passed tolistener
. In the prior version, it is always null for the callback listener.- See Also:
subscribe(EventListener)
,subscribe(EventListener,boolean)
-
subscribe
void subscribe(EventListener<T> listener, boolean async)
Subscribes a synchronous or asynchronous listener to this event queue. A synchronous listener works the same as a normal event listener, while an asynchronous listener is executed asynchronously in an working thread. Refer here for details.The use of synchronous listeners is straightforward -- they are just the same a normal event listener. Here is an example of using an asynchronous listener. In this example, we use an asynchronous listener to execute a long operation, a synchronous listener to update the desktop, and they communicate with each other with events.
There is another way to do the same job, callback, refer to
subscribe(EventListener,EventListener)
for example.<window title="long operation" border="normal"> <zscript> void print(String msg) { new Label(msg).setParent(inf); } </zscript> <button label="async long op"> <attribute name="onClick"><![CDATA[ if (EventQueues.exists("longop")) { print("It is busy. Please wait"); return; //busy } EventQueue eq = EventQueues.lookup("longop"); //create a queue String result; //subscribe async listener to handle long operation eq.subscribe(new EventListener() { public void onEvent(Event evt) { if ("doLongOp".equals(evt.getName())) { org.zkoss.lang.Threads.sleep(3000); //simulate a long operation result = "success"; //store the result eq.publish(new Event("endLongOp")); //notify it is done } } }, true); //asynchronous //subscribe a normal listener to show the result to the browser eq.subscribe(new EventListener() { public void onEvent(Event evt) { if ("endLongOp".equals(evt.getName())) { print(result); //show the result to the browser EventQueues.remove("longop"); } } }); //synchronous print("Wait for 3 seconds"); eq.publish(new Event("doLongOp")); //kick off the long operation ]]></attribute> </button> <vbox id="inf"/> </window>
The asynchronous event listener requires Server Push (
ServerPush
).If you want to show a busy message to cover a portion of the desktop, use
Clients.showBusy(org.zkoss.zk.ui.Component,String)
Note: this method must be called within an activated execution, i.e.,
Executions.getCurrent()
not null.An event listener can be subscribed multiple times, and it will be invoked multiple times if an event is published.
Even if this is an application-level or session-level event queue, the listener is subscribed for the current desktop only. If you want to use the same listener for multiple desktops, you have to subscribe them separately when the corresponding execution is available.
- Parameters:
listener
- the listenerasync
- whether the listener is asynchronous- See Also:
subscribe(EventListener)
,subscribe(EventListener, EventListener)
-
unsubscribe
boolean unsubscribe(EventListener<T> listener)
Unsubscribes a listener from the queue.Note: this method must be called within an activated execution, i.e.,
Executions.getCurrent()
not null.Notice that this method only unsubscribes the listener subscribed for this desktop. It doesn't check the listeners for other desktops even if this is an application-level or session-level event queue.
- Returns:
- true if the listener was subscribed.
-
isSubscribed
boolean isSubscribed(EventListener<T> listener)
Returns if an event listener is subscribed.Notice that this method only checks the listeners subscribed for this desktop. It doesn't check the listeners for other desktops even if this is an application-level or session-level event queue.
-
close
void close()
Closes the event queue. After closed, application cannot access any of its method.Don't call this method directly. It is called only internally. Rather, use
EventQueues.remove(java.lang.String)
instead.
-
isClose
boolean isClose()
Returns whether it is closed.- Since:
- 5.0.6
-
-