morpheus05 morpheus05 - 4 months ago 17
Java Question

Combine Swing event observables with other observables

I have a label which displays error messages. If you double click on it you get a big dialog showing the whole stack trace. I have two observables: One for the errors and one for the click events:

final ConnectableObservable<Notification> errorNotifications = pm
.getNotificationObservable()
.filter(notification -> notification.getType().isError() && !notification.getLongMessage().isEmpty())
.replay(1);

errorNotifications.connect();

SwingObservable.fromMouseEvents(dialog.getMessagePanel().getMessageLabel())
.map(MouseEvent::getClickCount)
.filter(number -> number >= 2)
.subscribe(integer -> errorNotifications
.take(1)
.subscribe(notification -> ErrorDialog.showError(dialog.getFrame(), "Error", notification.getLongMessage())));


I filter the notification observable to only show erros and replay the last error if I subscribe from it from inside my click observable.

Now my question is, are there any operators in RxJava by which I can do this more... neatly? I tried to use
combineLatest()
but this had the effect, that every time an error ocured the dialog would open.

In a more abstract way: I have two observables, one is like the "master": If the master observable (click observable) emits an item, the other observable (my error notifications) should emit the latest item.

Answer

Using another Observable in a subscription is often a design flaw.

You may check the flatMap operator in this documentation or in this response. It will help you to emits error notification when you emit another event.

For example, if you want to use flatMap operator with your code, it can be updated like this :

 final ConnectableObservable<Notification> errorNotifications = 
                                                  pm.getNotificationObservable()
                                                    .filter(notification -> notification.getType().isError() && !notification.getLongMessage().isEmpty())
                                                    .replay(1);

errorNotifications.connect();

SwingObservable.fromMouseEvents(dialog.getMessagePanel().getMessageLabel())
           .map(MouseEvent::getClickCount)
           .filter(number -> number >= 2)
           .flatMap(integer -> errorNotifications.take(1))
           .subscribe(notification -> ErrorDialog.showError(dialog.getFrame(), "Error", notification.getLongMessage())));