7

通过使用 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){
....
}

但我无法收到该事件。谁能让我知道我在哪里做错了?

4

4 回答 4

24

由于它们是两个活动,因此在尚未创建或处于停顿模式 ( )ActivitySubscriber时发布事件。您需要使用粘性事件,即ActivityReceiveronStop()

  • 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- 如果为真,则提供最近的粘性事件(与de.greenrobot.event.EventBus.postSticky(Object)此订阅者一起发布(如果事件可用)
    • priority = 0- 订阅者优先级影响事件传递的顺序。在同一交付线程中,优先级较高的订阅者将在其他优先级较低的订阅者之前收到事件。默认优先级为0。注意:优先级不影响不同线程模式的订阅者之间的传递顺序。

编辑 2

现在有一个专门的站点可以解决来自 lib 创建者的任何 Greenrobot EventBus 问题:

http://greenrobot.org/eventbus/

于 2013-02-04T06:18:44.920 回答
3
  1. 添加

dependencies { .. compile 'org.greenrobot:eventbus:3.0.0' .. }

进入 Modules Build gradle 的依赖部分

  1. 创建一个 MessageEvent 类,如

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

  1. 假设我们有 Fragment1 并且有一个按钮可以向 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;
    }

  1. 最后结束 MainActivity 听并做动作

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();
    }
}

于 2016-11-25T23:56:09.663 回答
1

在 ActivityReceiver 类中,替换

EventBus.getDefault().register(this); 

EventBus.getDefault().register(this, MyEvent.class);
于 2014-08-20T09:52:32.227 回答
0

这实际上取决于此代码存在的时间和地点。请记住,您必须先注册事件才能接收它们,并且注册发生在运行时,而不是编译时。

因此,您必须确保在注册第二个活动后发布该活动。我会简单地在以下几行中放置一些断点,并确保调试器在此处停止:

EventBus.getDefault().register(this); 

在你到达这里之前:

EventBus.getDefault().post(event);
于 2016-02-26T11:47:00.023 回答