问题
By using EventBus, I need to post an event(MyEvent) in an Activity and receive the event in another Activity in Android. I tried the greenrobot EventBus performance test project but could not get how to do it.
I tried in ActivitySubscriber
MyEvent event = new MyEvent();
EventBus.getDefault().post(event);
and tried to receive the event in ActivityReceiver as
EventBus.getDefault().register(this);
public void onEvent(MyEvent event){
....
}
but I am unable to receive the event. Can anyone let me know where am I doing wrong?
回答1:
Since they are two activities, ActivitySubscriber
posts the event while ActivityReceiver
is still not created, or is in stall mode (onStop()
). You need to use sticky events, i.e.
ActivitySubscriber.postSticky(...)
And for ActivityReceiver you have two options:
EventBus.getDefault().register(this)
and somewhere after thatEventBus.getDefault().getStickyEvent()
EventBus.getDefault().registerSticky()
and then using regularEventBus.getDefault().onEvent(...)
Updated: EventBus 3.0 changes the way to subscribe.
There is no need of method names which end up with specific suffixes but rather annotations.
How to use version 3:
//// in your build.gradle
compile 'de.greenrobot:eventbus:3.0.0-beta1'
// alternatively you can target latest whatever currently
// compile 'de.greenrobot:eventbus:+'
//// from a class which needs to dispatch an event
// posting an event is as before, no changes
// here we dispatch a sticky event
EventBus.getDefault().postSticky(myStickyEvent);
//// from your class which needs to listen
// method name can be any name
// any of subscribe params is optional, i.e. can use just @Subscribe
@Subscribe(threadMode = ThreadMode.MainThread, sticky = true, priority = 1)
public void onEventBusEvent(@Nullable final StickyEvent stickyEvent) {
if (stickyEvent != null) {
...
// optionally you can clean your sticky event in different ways
EventBus.getDefault().removeAllStickyEvents();
// EventBus.getDefault().removeStickyEvent(stickyEvent);
// EventBus.getDefault().removeStickyEvent(StickyEvent.class);
}
}
For more details and comparison of version 3:
- http://androiddevblog.com/eventbus-3-droidcon/
- http://androiddevblog.com/wordpress/wp-content/uploads/EventBus3.pdf
Some details extracted from the sources:
ThreadMode.PostThread
Subscriber will be called in the same thread, which is posting the event. This is the default. Event delivery implies the least overhead because it avoids thread switching completely. Thus this is the recommended mode for simple tasks that are known to complete is a very short time without requiring the main thread. Event handlers using this mode must return quickly to avoid blocking the posting thread, which may be the main thread.
ThreadMode.MainThread
Subscriber will be called in Android's main thread (sometimes referred to as UI thread). If the posting thread is the main thread, event handler methods will be called directly. Event handlers using this mode must return quickly to avoid blocking the main thread.
ThreadMode.BackgroundThread
Subscriber will be called in a background thread. If posting thread is not the main thread, event handler methods will be called directly in the posting thread. If the posting thread is the main thread, EventBus uses a single background thread, that will deliver all its events sequentially. Event handlers using this mode should try to return quickly to avoid blocking the background thread.
ThreadMode.Async
Event handler methods are called in a separate thread. This is always independent from the posting thread and the main thread. Posting events never wait for event handler methods using this mode. Event handler methods should use this mode if their execution might take some time, e.g. for network access. Avoid triggering a large number of long running asynchronous handler methods at the same time to limit the number of concurrent threads. EventBus uses a thread pool to efficiently reuse threads from completed asynchronous event handler notifications.
- default values for
@Subscribe
threadMode = ThreadMode.PostThread
sticky = false
- If true, delivers the most recent sticky event (posted withde.greenrobot.event.EventBus.postSticky(Object)
to this subscriber (if event available)priority = 0
- Subscriber priority to influence the order of event delivery. Within the same delivery thread, higher priority subscribers will receive events before others with a lower priority. The default priority is 0. Note: the priority does NOT affect the order of delivery among subscribers with different thread modes.
Edit 2
There is a dedicated site now for any Greenrobot EventBus questions from the creator of the lib:
http://greenrobot.org/eventbus/
回答2:
- Add
dependencies {
..
compile 'org.greenrobot:eventbus:3.0.0'
..
}
into dependencies section of Modules Build gradle
- Create a MessageEvent class like
public final class MessageEvent {
private MessageEvent() {
throw new UnsupportedOperationException("This class is non-instantiable");
}
public static class Message1{
public String str1;
public Message1(String str) {
str1 = str;
}
}
public static class Message2{
public String str2;
public Message2(final String str) {
str2 = str;
}
}
}
// so on
- Assume that we have Fragment1 and there is a button that suppose to send messages to MainActivity
public class Fragment1 extends Fragment {
private View frView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup
container, Bundle savedInstanceState) {
frView = inflater.inflate(R.layout.fragment1,
container, false);
btn = (Button) frView.findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
frView.setBackgroundColor(Color.RED);
EventBus.getDefault().post(new MessageEvent.Message1("1st message"));
EventBus.getDefault().post(new MessageEvent.Message2("2nd message"));
}
});
return frView;
}
- End finally MainActivity to listen and do action
public class MainActivity extends AppCompatActivity {
@Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
protected void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Fragment1 Fragment1 = new Fragment1();
getFragmentManager().beginTransaction().replace(
R.id.activity_main, Fragment1,
"Fragment 1").commit();
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage1(MessageEvent.Message1 event) {
Toast.makeText(getApplication(), event.str1,
Toast.LENGTH_LONG).show();
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage2(MessageEvent.Message2 event) {
Toast.makeText(getApplication(), event.str2,
Toast.LENGTH_LONG).show();
}
}
回答3:
Inside ActivityReceiver class, replace
EventBus.getDefault().register(this);
with
EventBus.getDefault().register(this, MyEvent.class);
回答4:
It really depends when and where this code exists. Remember that you must register for the events before you can receive them, and registering takes place at runtime, not compile time.
So, you must ensure that you are posting the event after you have registered the second activity. I would simply put some breakpoints on the following lines and ensure that the debugger stops here:
EventBus.getDefault().register(this);
before you get to here:
EventBus.getDefault().post(event);
来源:https://stackoverflow.com/questions/14263183/greenrobot-eventbus-post-event-in-android