I'm used to programming in C#, and one thing I miss about Java is that it doesn't seem to have C#'s nice built-in event handling capabilities:
// define event signature
public delegate void SomeEventHandler();
class SomeEventGenerator {
// define subscribable event property
public event SomeEventHandler SomeEvent;
protected void OnSomeEvent() {
if (SomeEvent != null) {
SomeEvent();
}
}
}
class SomeEventClient {
public SomeEventClient(SomeEventGenerator eg) {
// subscribe
eg.SomeEvent += new SomeEventHandler(eg_SomeEvent);
// do some stuff
// unsubscribe
eg.SomeEvent -= new SomeEventHandler(eg_SomeEvent);
}
private void eg_SomeEvent() {
// handle event
}
}
What's the best way to get something similar and lightweight in Java/Android which has the ability to subscribe/unsubscribe multiple event clients and call all subscribed clients at once?
You would want to look into the concept of listeners in java. I found a very good article called "C# from a Java developers perspective" that you might want to check out.
http://www.25hoursaday.com/CsharpVsJava.html
Related
I'm designing SDK for Android.
As a web developer, I'm very used to and comfortable with callbacks, and as the SDK will include many async operations, I'm not sure what is the most common or "best" way to implement such a behavior on Android (or Java in general).
I've come up with a couple of options:
1) Listener interface - the developer that will use the SDK will implement a listener interface that will include all the callbacks, for example:
interface ISDKListener {
public void onA();
public void onB();
}
class SDK {
private ISDKListener _listener;
public SDK(ISDKListener listener) {
_listener = listener
}
public void a() {
// Do stuff
_listener.onA();
}
public void b() {
// Do stuff
_listener.onB();
}
}
As a web developer, using JS that looks a bit too much for me, "forcing" the user (developer) to implement all the listeners in advance, when he might no even use all of them.
2) Single listeners setters
Basically set a listener to each async method. For example:
interface ISDKCallback {
public void onComplete();
}
class SDK {
private ISDKCallback _aCb;
private ISDKCallback _bCb;
public void setAListener(ISDKCallback aCb) {
_aCb = aCb
}
public void a() {
// Do stuff
if (_aCb != null) _aCb.onComplete();
}
public void setBListener(ISDKCallback bCb) {
_bCb = bCb
}
public void b() {
// Do stuff
if (_bCb != null) _bCb.onComplete();
}
}
3) Same as #2, but separate success and errors:
interface ISDKCallback {
public void onSuccess();
public void onError(Exception e);
}
class SDK {
private ISDKCallback _aCb;
public void setAListener(ISDKCallback aCb) {
_aCb = aCb
}
public void a() {
try {
// Do stuff
if (_aCb != null) _aCb.onSuccess();
} catch (Exception e) {
if (_aCb != null) _aCb.onError(e);
}
}
}
4) Combining #1 and #3 - a complete listener with all the callbacks, but each callback will be 2 callbacks, one for success and one for errors:
interface ISDKListener {
public void onA();
public void onAError(Exception e);
public void onB();
public void onBError(Exception e);
}
class SDK {
private ISDKListener _listener;
public SDK(ISDKListener listener) {
_listener = listener
}
public void a() {
try {
// Do stuff
_listener.onA();
} catch (Exception e) {
_listener.onAError(e);
}
}
public void b() {
try {
// Do stuff
_listener.onB();
} catch (Exception e) {
_listener.onBError(e);
}
}
}
The 3rd one seems most "natural" for me, due to the separation between success and error (like the promise then and catch on JS) and setting each callback separately. Actually the most natural to me was to pass the callback when I call the method, but I did not found such implementation anywhere in Java as far as I've searched.
Which one is the most common and will be the most "natural" to most Android/Java developers? Are there any other suggestions for implementing callbacks in that platform?
EDIT:
To clarify, the callbacks are either for HTTP responses to HTTP requests or BLE communication, for example method a will send some request over BLE to a BLE peripheral, and the callback for a will be called when the peripheral returned a response (the mobile and peripheral are implementing a client-server protocol over BLE)
I'm not the biggest expert out there but if you're asking which is the most common implementation I would say numer 1. You can take a look at a lot of libraries out there, I used a lot of them myself and this is what I found to be the most used solution.
One good example would be the usage of ExoPlayer (I'm choosing it just because I'm working on it at the moment).
As you can see the activity includes an instance of the player + all the objects it needs like the BandwidthMeter and implements ExoPlayer.EventListener inheriting all the callbacks like onPlayerStateChanged.
Even the Android API itself makes use of this pattern, maybe too much. But this is another topic I guess. A lot of people finds this approach a bit confusing because you end up with a callback hell and I'm with them.
Edit
Another good example of a different approach can be found in the Google API Client (which suits your situation better).
As you can see you connect to the Client with two listener, and you have another optional listener for errors with a different interface and an additional callback.
Conclusion
I guess in the end it really depends on you: solution 1 and 2 both look good to me. Number 3 will work too but I'm not too familiar with it, maybe this is a sign that it's not a widely used pattern in Android Development.
In general, callbacks or listeners interfaces are a valid approach, but I would choose Android LiveData. It's an observational data holder which wraps your data and let others listen to your changes. In your case, I would expose LiveData with some kind of model, and the users of your sdk would then observe your return value of type LiveData for future changes in the data. Thus the users of your sdk won't have to implement nothing.
I've just wrote a blog post where I go over callbacks (as well as event bus and LiveData), describing the scenarios in which we should use one over another and the pros and cons of using one rather than the other. I think it may be useful to you:
When and why to use LiveData
I just can't figure out how to remove listener when I have some event executed. I have some leaking issue using websockets, and this can probaly fix it.
final WebSocket w = asyncHttpClient.prepareGet(url)
.execute(new WebSocketUpgradeHandler.Builder().build())
.get();
w.addWebSocketListener(new WebSocketTextListener() {
public void onMessage(String message) {
listener.onMessage(responseMessage);
// Here is the place I want to do my w.removeWebSocketListener(l);
}
#Override
public void onFragment(String s, boolean b) {
}
public void onOpen(WebSocket websocket) {
}
#Override
public void onClose(WebSocket webSocket) {
}
#Override
public void onError(Throwable throwable) {
}
});
The problem is when I create WebSocketTextListener lis = new .... and passing in there is something like one object need other object and other object is dependent on this, and I'm still now allowed to do what I want.
Looks like it is something simple, but can't figure out.
Normally event listeners can be removed with a removeXXXListener method. But it requires that you provide the exact same event listener instance as parameter. You can store the event listener and later remove it using the same reference. But since you, in the onMessage message already are inside the scope of the event listener, using this should work.
Try something like
listener.onMessage(responseMessage);
// Here is the place I want to do my w.removeWebSocketListener(l);
w.removeWebSocketListener(this);
Using "this" in anonumous inner class is the way to solve problem. But, it is muck better to refactor code, to avoid using anonumous classes, for testability and better understanding.
I'm implementing a client-server system where the client is in a continuous blocking read loop listening for messages from the server. When a message is received I'd like to raise an "event" based on the type of the message, which other GUI classes may add listeners to. I'm more familiar with C# events so I am still getting used to the Java way of doing things.
There will be many message types so I will need an interface for each, call it MessageTypeAListener, MessageTypeBListener, etc., each of which will contain one handle method, which my GUI classes will implement. However, there will be be many types and instead of maintaining a list of listeners per type and having several "fire" methods I wanted to have one big listener list and a typed fire method. Then the fire method could say "only fire listeners whose type is what I specify."
So for example (pseudocode):
ListenerList.Add(MessageTypeAListener);
ListenerList.Add(MessageTypeBListener);
<T> fire(message) {
ListenerList.Where(type is T).handle(message)
}
...
fire<MessageTypeAListener>(message);
However, type erasure seems to be making this difficult. I could try casting and catching exceptions but that seems wrong. Is there a clean way of implementing this or is it just wiser to keep a separate list of listeners for every type, even though there will be tons of types?
I implemented something like this, cause I have a visceral dislike of Java's EventListenerList. First, you implement a generic Listener. I defined the listener based upon the Event it was receiving, with basically one method
interface GenericListener<T extends Event> {
public void handle(T t);
}
This saves you having to define ListenerA, ListernerB etc... Though you could do it your way with ListenerA, ListenerB, etc, all extending some base like MyListener. Both ways have plusses and minuses.
I then used a CopyOnWriteArraySet to hold all these listeners. A set is something to consider cause all too often listeners get added twice by sloppy coders. YMMV. But, effectively you have a Collection<GenericListener<T extends Event>> or a Collection<MyListener>
Now, as you've discovered, with type erasure, the Collection can only hold one type of listener. That is often a problem. Solution: Use a Map.
Since I'm basing everything upon the event, I used
Map<Class<T extends Event>, Collection<GenericListener<T extends Event>>>
based upon the class of the event, get the list of listeners who want to get that event.
Your alternative is to base it upon the class of the listener
Map<Class<T extends MyListener>, Collection<MyListener>>
There's probably some typos above...
Old-fashioned pattern approach, using Visitor pattern:
class EventA {
void accept(Visitor visitor) {
System.out.println("EventA");
}
}
class EventB {
void accept(Visitor visitor) {
System.out.println("EventB");
}
}
interface Visitor {
void visit(EventA e);
void visit(EventB e);
}
class VisitorImpl implements Visitor {
public void visit(EventA e) {
e.accept(this);
}
public void visit(EventB e) {
e.accept(this);
}
}
public class Main {
public static void main(String[] args) {
Visitor visitor = new VisitorImpl();
visitor.visit(new EventA());
}
}
More modern approach is just to have Map between classes of events, which should not derive each other, and respective handlers of these events. This way you avoid disadvantages of Visitor pattern (which is, you'll need to change all your visitor classes, at least, base of them, every time you add new Event).
And another way is to use Composite pattern:
interface Listener {
void handleEventA();
void handleEventB();
}
class ListenerOne implements Listener {
public void handleEventA() {
System.out.println("eventA");
}
public void handleEventB() {
// do nothing
}
}
class CompositeListener implements Listener {
private final CopyOnWriteArrayList<Listener> listeners = new CopyOnWriteArrayList<Listener>();
void addListener(Listener l) {
if (this != l)
listeners.add(l);
}
public void handleEventA() {
for (Listener l : listeners)
l.handleEventA();
}
public void handleEventB() {
for (Listener l : listeners)
l.handleEventB();
}
}
After going through iterations of just about everyone's suggestions here, I ended up going a very slightly modified route of the standard Listener interfaces and listener lists. I started with Swing's EventListenerList, only to be disappointed with the amount of add/remove methods for dozens of message types. I realized this could not be condensed while still maintaining a single EventListenerList, so I started thinking about a separate list for each type. This makes it similar to .NET events where each event holds its own list of delegates to fire when raised. I wanted to avoid tons of add/remove methods, so I made a quick Event class that just looks like this:
public class Event<T extends EventListener> {
private List<T> listeners = new ArrayList<T>();
public void addListener(T listener) {
listeners.add(listener);
}
public void removeListener(T listener) {
listeners.remove(listener);
}
public List<T> getListeners() {
return listeners;
}
}
Then I keep several instances of this class around, each typed according to a listener, so Event<MessageTypeAListener>, etc. My classes can then call the add method to add themselves to that particular event. I would've like to be able to call a generic Raise method on the Event instance to then fire all the handlers, but I did not want them to all have to have the same "handle" method, so this was not possible. Instead, when I'm ready to fire the listeners, I just do
for (MessageTypeAListener listener : messageTypeAEvent.getListeners())
listener.onMessageTypeA(value);
I'm sure this is not a new idea and has probably been done before and in better/more robust ways, but it's working great for me and I'm happy with it. Best of all, it's simple.
Thanks for all the help.
If you only have simple events, i.e. events without data or where all events have the same data types, enum could be a way forward:
public enum Event {
A,
B,
C
}
public interface EventListener {
void handle(Event event);
}
public class EventListenerImpl implements EventListener {
#Override
public void handle(Event event) {
switch(event) {
case A:
// ...
break;
}
}
}
public class EventRegistry {
private final Map<Event, Set<EventListener>> listenerMap;
public EventRegistry() {
listenerMap = new HashMap<Event, Set<EventListener>>();
for (Event event : Event.values()) {
listenerMap.put(event, new HashSet<EventListener>());
}
}
public void registerEventListener(EventListener listener, Event event) {
Set<EventListener> listeners = listenerMap.get(event);
listeners.add(listener);
}
public void fire(Event event) {
Set<EventListener> listeners = listenerMap.get(event);
for (EventListener listener : listeners) {
listener.handle(event);
}
}
}
Comments:
The switch statement in the EventListnerImpl may be omitted if it is only registered to a single event, or if it should always act in the same way regardless of which Event it receives.
The EventRegister has stored the EventListener(s) in a map, meaning that each listener will only get the kind of Event(s) that it has subscribed to. Additionally, the EventRegister uses Sets, meaning that an EventListener will only receive the event at most once (to prevent that the listener will receive two events if someone accidentally registers the listener twice).
I'm starting with GWT and learning Event bus concepts now. I find this solution extremely complicated. So I tried to simplify it by writing prototype by myself to see all problems.
At first I will write about my understanding of event bus (that can be completely wrong).
We have events like this
public class FooEvent extends GwtEvent<FooHandler> {
public static Type<FooHandler> TYPE = new Type<FooHandler>(); //as event type integer ID
//for.. hm.. probably some inner use in Event Bus
#Override public Type<FooHandler> getAssociatedType() {
return TYPE;
}
//for handling
#Override protected void dispatch(FooHandler handler) {
handler.someMethod(this);
}
}
handler interface,
public interface FooHandler extends EventHandler {
void someMethod(FooEvent event);
}
usage
eventBus.addHandler(FooEvent.TYPE, new FooHandler() {
#Override
public void someMethod(FooEvent event) {
//bla-bla
}
});
eventBus.fireEvent(new FooEvent());
Thats it. And now my prototype.
//replaced GwtEvent
interface UniGwtEvent {
}
//than, event pretty simple
public class FooEvent extends UniGwtEvent {
}
//replaced GwtEventHandler. You should not create special handler class per event!
public interface UniEventHandler<T extends UniGwtEvent> {
void handle(T event);
}
//event bus prototype(in pseudocode)
class UniEventBus {
//map. keys getted from class. as I understand, it's possible from GWT 1.5 see http://code.google.com/p/google-web-toolkit/issues/detail?id=370
public <T extends UniGwtEvent> void addListener(Class<T> event, UniEventHandler<T> handler){
map.put(event.getName(), handler);
}
public void fireEvent(UniGwtEvent event){
if(map.contains(event.getClass().getName())){
map.get(event).handle(event);
}
}
}
usage
eventBus.addListener(FooEvent.class, new UniEventHandler<FooEvent>(){
#Override
public void handle(FooEvent event) {
bla-bla
}
});
eventBus.fireEvent(new FooEvent());
I think this solution is much better since you shouldn't make unnecessary Type manipulation and create Handler Class per event. I see only one disadvantage - you should specify generic type on handler creation. But I suppose there are many other disadvantages or ever issues that makes this solution impossible. What are they?
There is no obvious advantage to using your implementation. As I read it there are two differences between yours and GWT's EventBus:
Using Strings instead of Type objects to bind event handlers to event types. This is not a meaningful difference - there's no penalty to having more types in your application and I suspect that, at runtime, Strings will use slightly more resources than Types.
Dispatching events to the appropriate handlers directly instead of delegating to the event type. I prefer GWT's approach here because it affords flexibility in how events are dispatched. One might, for example, want handlers to implement two different methods that are invoked depending on the context of the event. Take the following (trivial) example:
public class ExampleEvent extends GwtEvent<ExampleEvent.Handler> {
public interface Handler extends EventHandler {
void onExample(Integer id);
void onExample(String name);
}
private final Integer id;
private final String name;
public ExampleEvent(Integer id) {
this.id = id;
this.name = null;
}
public ExampleEvent(String name) {
this.name = name;
this.id = null;
}
public void dispatch(Handler handler) {
if (name != null) {
handler.onExample(name);
} else {
handler.onExample(id);
}
}
}
In this case delegating dispatch to the event allows us to take an action that must be performed for every handler (determining whether the event contains an id or a name) without requiring that the test be performed in every individual event handler.
I recommend using GWT's EventBus implementation - it works and it is tested.
There are other event bus implementations out there that will do a good job. I recently created a very efficient event bus (Mbassador) that I have been using in production for a while now. It's hosted on github and you are invited to take a look.
https://github.com/bennidi/mbassador
Another option would be to use google guavas event bus but it lacks some useful features (which is why I implemented my own solution)
EDIT: I created a performance and feature comparison for a selection of available event bus implementations including Guava, MBassador and some more. The results are quite interesting. Check it out here
http://codeblock.engio.net/?p=37
I am trying to design a Java system that is simliar to the concept of c# delegates.
Here is the basic functionality i wish to achieve:
public class mainform
{
public delegate onProcessCompleted
//......
processInformation()
{
onProcessCompleted(this);
}
//......
}
//PLUGIN
public class PluginA
{
public PluginA()
{
//somehow subscribe to mainforms onProcessingCompleted with callback myCallback()
}
public void myCallback(object sender)
{
}
}
I have read through this site: http://www.javaworld.com/javaqa/2000-08/01-qa-0804-events.html?page=1
They make reference to implementing the whole 'subscription list' manually. But the code is not a complete example, and I'm so used to c# that I'm having trouble grasping how I could do it in java.
Does anyone have a working examle of this that I could see?
thanks
Stephanie
In Java you don't have function delegates (effectively method references); you have to pass an entire class implementing a certain interface. E.g.
class Producer {
// allow a third party to plug in a listener
ProducerEventListener my_listener;
public void setEventListener(ProducerEventListener a_listener) {
my_listener = a_listener;
}
public void foo() {
...
// an event happened; notify the listener
if (my_listener != null) my_listener.onFooHappened(new FooEvent(...));
...
}
}
// Define events that listener should be able to react to
public interface ProducerEventListener {
void onFooHappened(FooEvent e);
void onBarOccured(BarEvent e);
// .. as many as logically needed; often only one
}
// Some silly listener reacting to events
class Consumer implements ProducerEventListener {
public void onFooHappened(FooEvent e) {
log.info("Got " + e.getAmount() + " of foo");
}
...
}
...
someProducer.setEventListener(new Consumer()); // attach an instance of listener
Often you have trivial listeners that you create via an anonymous classes in place:
someProducer.setEventListener(new ProducerEventListener(){
public void onFooHappened(FooEvent e) {
log.info("Got " + e.getAmount() + " of foo");
}
public void onBarOccured(BarEvent e) {} // ignore
});
If you want to allow many listeners per event (as e.g. GUI components do), you manage a list which you usually want to be synchronized, and have addWhateverListener and removeWhateverListener to manage it.
Yes, this is insanely cumbersome. Your eyes don't lie to you.