Using Guava's EventBus, I want to be able to post from a background thread (called "background") to a specific thread (in this case, thread "main") that updates the UI. I thought the following would work, but this calls the subscriber code from the background thread:
package com.example;
import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import com.google.common.util.concurrent.MoreExecutors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class EventBusTester {
private static final Logger log = LoggerFactory.getLogger(EventBusTester.class);
public static void main(String... args) {
new EventBusTester().run();
}
private void run() {
log.info("Starting on thread {}.", Thread.currentThread().getName());
final EventBus eventBus = new AsyncEventBus(MoreExecutors.sameThreadExecutor());
eventBus.register(this);
Thread background = new Thread(new Runnable() {
@Override
public void run() {
long now = System.currentTimeMillis();
eventBus.post(now);
log.info("Posted {} to UI on thread {}.", now, Thread.currentThread().getName());
}
}, "background");
background.start();
}
@Subscribe
public void updateUi(Long timestamp) {
log.info("Received {} on UI on thread {}.", timestamp, Thread.currentThread().getName());
}
}
This prints the following:
02:20:43.519 [main] INFO com.example.EventBusTester - Starting on thread main.
02:20:43.680 [background] INFO com.example.EventBusTester - Received 1387848043678 on UI on thread background.
02:20:43.680 [background] INFO com.example.EventBusTester - Posted 1387848043678 to UI on thread background.
So my questions are:
I'd rather stay with pure Guava, though.
Thanks!
If you use an EventBus
instance then the @Subscribe
method will be executed on the same thread that posted the event.
If you want to do something different then use an AsyncEventBus
where you can provide an Executor
to define the exact behavior in case of an event gets posted.
For instance, on Android to make every @Subscribe
method run on the main thread you can do the following:
EventBus eventBus = new AsyncEventBus(new Executor() {
private Handler mHandler;
@Override
public void execute(Runnable command) {
if (mHandler == null) {
mHandler = new Handler(Looper.getMainLooper());
}
mHandler.post(command);
}
});
The Looper.getMainLooper()
returns the application's main looper, which lives on the main thread of the application.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With