通过使用EventBus,我需要在Activity中发布一个事件(MyEvent)并在Android中的另一个Activity中接收该事件。我尝试了greenrobot EventBus性能测试项目,但无法完成如何操作。
我尝试了 ActivitySubscriber
MyEvent event = new MyEvent();
EventBus.getDefault().post(event);
并尝试以 ActivityReceiver 作为
接收活动EventBus.getDefault().register(this);
public void onEvent(MyEvent event){
....
}
但我无法收到该活动。任何人都可以让我知道我在哪里做错了吗?
答案 0 :(得分:23)
由于它们是两项活动,ActivitySubscriber
会发布事件,而ActivityReceiver
仍未创建,或处于停顿模式(onStop()
)。您需要使用粘性事件,即
ActivitySubscriber.postSticky(...)
对于ActivityReceiver,您有两种选择:
EventBus.getDefault().register(this)
以及EventBus.getDefault().getStickyEvent()
EventBus.getDefault().registerSticky()
然后使用常规EventBus.getDefault().onEvent(...)
<强>更新强> EventBus 3.0改变了订阅的方式。
不需要最终具有特定后缀的方法名称,而是注释。
如何使用版本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);
}
}
有关版本3的更多详细信息和比较:
从资料来源提取的一些细节:
ThreadMode.PostThread
将在同一个帖子中调用订阅者,该帖子将发布该事件。这是默认值。事件传递意味着开销最小,因为它完全避免了线程切换。因此,对于已知完成的简单任务,这是一个推荐的模式,非常短的时间而不需要主线程。使用此模式的事件处理程序必须快速返回以避免阻止发布线程,这可能是主线程。
ThreadMode.MainThread
将在Android的主线程(有时称为UI线程)中调用订阅者。如果发布线程是主线程,则将直接调用事件处理程序方法。使用此模式的事件处理程序必须快速返回以避免阻塞主线程。
ThreadMode.BackgroundThread
将在后台线程中调用订阅者。如果发布线程不是主线程,则将在发布线程中直接调用事件处理程序方法。如果发布线程是主线程,则EventBus使用单个后台线程,该线程将按顺序传递其所有事件。使用此模式的事件处理程序应尝试快速返回以避免阻塞后台线程。
ThreadMode.Async
事件处理程序方法在单独的线程中调用。这始终独立于发布线程和主线程。发布事件永远不会等待使用此模式的事件处理程序方法。如果执行可能需要一些时间,例如事件处理程序方法应使用此模式。用于网络访问。避免同时触发大量长时间运行的异步处理程序方法来限制并发线程数。 EventBus使用线程池从已完成的异步事件处理程序通知中有效地重用线程。
@Subscribe
的值
threadMode = ThreadMode.PostThread
sticky = false
- 如果为true,则会向此订阅者发送最新的粘性事件(以de.greenrobot.event.EventBus.postSticky(Object)
发布(如果可用的话))priority = 0
- 订阅者优先级,以影响事件传递的顺序。在同一个传递线程中,较高优先级的订户将在优先级较低的其他订户之前接收事件。默认优先级为0.注意:优先级 NOT 会影响具有不同线程模式的订阅者之间的传递顺序。现在有来自lib创建者的任何Greenrobot EventBus问题的专用网站:
答案 1 :(得分:2)
dependencies {
..
compile 'org.greenrobot:eventbus:3.0.0'
..
}
进入Modules Build gradle
的依赖项部分
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
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;
}
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();
}
}
答案 2 :(得分:1)
在ActivityReceiver类中,替换
EventBus.getDefault().register(this);
与
EventBus.getDefault().register(this, MyEvent.class);
答案 3 :(得分:0)
这实际上取决于此代码存在的时间和位置。请记住,您必须在接收事件之前注册事件,并且注册在运行时进行,而不是在编译时进行。
因此,您必须确保在注册第二项活动后发布事件。我只想在以下几行中加入一些断点,并确保调试器在此处停止:
EventBus.getDefault().register(this);
在你到达之前:
EventBus.getDefault().post(event);