Simple BusProvider.getInstance().post()
bring exception not main thread
.
How to send event from Service to Activity with Otto event bus?
-
By default Otto uses the MAIN thread (see thread enforcement: http://square.github.com/otto/). Are you trying to post FROM another thread? Include example code and your stack trace. – Charlie Collins Mar 15 '13 at 12:18
-
Another way of achieving this is to use `runOnUiThread`, provided there is access to an Activity. Not very clean but will do the job. – ticofab Jun 18 '15 at 10:55
7 Answers
To post from any thread (main or background) and receive on the main thread, try something like
public class MainThreadBus extends Bus {
private final Handler mHandler = new Handler(Looper.getMainLooper());
@Override
public void post(final Object event) {
if (Looper.myLooper() == Looper.getMainLooper()) {
super.post(event);
} else {
mHandler.post(new Runnable() {
@Override
public void run() {
MainThreadBus.super.post(event);
}
});
}
}
}
Note: credit goes to Jake Wharton and "pommedeterresaute" at https://github.com/square/otto/issues/38 for the general approach. I just implemented it with a wrapper class rather than a subclass.

- 4,484
- 3
- 27
- 35

- 6,012
- 2
- 32
- 51
-
3Thanks. So as of now, does **Bus bus2 = new Bus(ThreadEnforcer.MAIN);** resolve it? – Thuy Trinh Feb 28 '14 at 16:27
-
3For me `ThreadEnforcer.MAIN` did not resolve it, but the code provided here. – Konrad Reiche May 20 '14 at 09:16
-
@platzhirsch from the doc: _If you are not concerned on which thread interaction is occurring, instantiate a bus instance with ThreadEnforcer.ANY_ – gderaco Jul 06 '14 at 15:31
-
@gdrc Thanks for catching up on this. After looking into the source code it became clear. I thought `ThreadEnforcer.ANY` is the default. – Konrad Reiche Jul 06 '14 at 17:57
-
2
-
Any idea if this would work on a `Wear` device using `WearableListenerService`? – theblang Oct 29 '14 at 00:55
-
-
-
To post from any thread (main or background) and receive on the main thread, use the following MainThreadBus
instead of a vanilla Bus
public class MainThreadBus extends Bus {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void post(final Object event) {
if (Looper.myLooper() == Looper.getMainLooper()) {
super.post(event);
} else {
handler.post(new Runnable() {
@Override
public void run() {
MainThreadBus.super.post(event);
}
});
}
}
}
This is based on Andy Dennie's answer.
There is no need to both extend and wrap a Bus
object, do one or the other. In Dennie's answer, which is effectively a wrapper, the Bus
base class is just being used like an interface, all the functionality is overwritten.
It would work even if you removed the Bus
base class unless you happened to reference the MainThreadBus
via a Bus
reference.

- 16,283
- 6
- 45
- 66

- 2,604
- 2
- 26
- 30
-
1My answer implemented an interface which was part of Otto at the time, but has since been removed (and someone edited my answer to make it extend rather than implement); that's why it looks odd now. In my example I wanted to wrap another bus that was not limited to being used on the main thread only. – Andy Dennie Apr 29 '14 at 19:03
bus = new Bus(ThreadEnforcer.ANY); is the clear solution to this problem. Its all you have to do.

- 2,139
- 5
- 32
- 42
Best implementation custom bus class for me
public class AndroidBus extends Bus {
private final Handler mainThread = new Handler(Looper.getMainLooper());
@Override
public void post(final Object event) {
if (Looper.myLooper() == Looper.getMainLooper()) {
super.post(event);
} else {
mainThread.post(() -> AndroidBus.super.post(event));
}
}
}

- 1,173
- 12
- 9
I did it simply:
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
bus.post(event);
}
});

- 6,405
- 6
- 28
- 69

- 20,649
- 15
- 100
- 138
Just create the BasicBus
with ThreadEnforcer.NONE
to post event from non-main threads. The mentioned ThreadEnforcer.MAIN
is exactly the opposite (and the default), which accepts only posts from the main-thread.

- 1
-
1It's unlikely that this is a usable answer. The OP says "... to Activity ...", which implies to me that the processing needs to be done on the UI or main thread. – RenniePet Nov 22 '15 at 06:33