I've started working on an existing project (an sdk) at work, and the code base uses listeners like there's no tomorrow. Pretty much every second method takes some sort of listener argument and I have yet to find an occurrence where the listener is not the calling class or an anonymous class declared when the method is called.
My question is: when/why is it appropriate to use a Listener over Future<> in this way?
// Util methods
static void postSuccess(Listener listener, Object object) {
Util.runOnUI(() -> { listener.success(object); });
}
static void postError(Listener, Exception ex) {
Util.runOnUI(() -> { listener.failure(ex); });
}
void foo ( Bar bar, Listener listener ) {
executor.submit(() -> {
try {
// work_on() is a potentially long running function
Result res = work_on( bar );
Util.postSuccess(listener, res)
}
catch (Exception ex) {
Util.postError(listener, ex);
}
}
}
In the above code the caller has no control over when the listener's method is invoked. The following code would allow the caller to decide whether to wait or check it later and generally seems to provide more control:
Future<Result> foo ( Bar bar ) {
return executor.submit(() -> { return workOn( bar ) };
}
Apologies if I'm missing something obvious, I'm only out of college three months, but this listener code smells bad to me.
Util.postSuccess(Listener<T>, T object)
andUtil.postFailure(Listener<T> listener, T object)
which run the corresponding listener method on another thread.Util.runOnUI()
do? To me it implies a Swing application, which requires a callback pattern to avoid blocking the event dispatch thread. With aFuture
, you either risk blocking by callingget()
, or waste time callingisDone()
.