【问题标题】:greenrobot EventBus post event in AndroidAndroid中的greenrobot EventBus发布事件
【发布时间】:2013-01-10 16:57:46
【问题描述】:

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

但我无法收到该活动。谁能告诉我我哪里做错了?

【问题讨论】:

标签: android event-bus


【解决方案1】:

由于它们是两个活动,ActivitySubscriberActivityReceiver 仍未创建或处于停顿模式 (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

    Subscriber 将在 Android 的主线程(有时称为 UI 线程)中调用。如果发布线程是主线程,将直接调用事件处理方法。使用此模式的事件处理程序必须快速返回以避免阻塞主线程。

  • ThreadMode.BackgroundThread

    订阅者将在后台线程中被调用。如果发布线程不是主线程,则事件处理方法将直接在发布线程中调用。如果发布线程是主线程,EventBus 使用单个后台线程,它将按顺序传递其所有事件。使用此模式的事件处理程序应尽量快速返回以避免阻塞后台线程。

  • ThreadMode.Async

    事件处理程序方法在单独的线程中调用。这始终独立于发布线程和主线程。发布事件从不等待使用此模式的事件处理程序方法。如果事件处理程序方法的执行可能需要一些时间,则应使用此模式,例如用于网络访问。避免同时触发大量长时间运行的异步处理程序方法,以限制并发线程数。 EventBus 使用线程池有效地重用已完成异步事件处理程序通知中的线程。

  • @Subscribe默认
    • threadMode = ThreadMode.PostThread
    • sticky = false - 如果为 true,则将最近的粘性事件(与 de.greenrobot.event.EventBus.postSticky(Object) 一起发布给此订阅者(如果事件可用))
    • priority = 0 - 订阅者优先级影响事件传递的顺序。在同一交付线程中,优先级较高的订阅者将在其他优先级较低的订阅者之前收到事件。默认优先级为 0。注意:优先级不会影响具有不同线程模式的订阅者之间的传递顺序。

编辑 2

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

http://greenrobot.org/eventbus/

【讨论】:

  • 为什么它显示 registerSticky(Object, Class>, Class>...) 类型 EventBus 已弃用
  • 现在正确的实现是:@Subscribe(threadMode = ThreadMode.MainThread) public void onEventBusEvent(YourEvent event) { // 'onEventBusEvent' can be named as you'd like }
  • 这到底是什么......为什么greenrobots网站上没有更新docu?
  • 如果我从 onEvent 调用,我应该在哪个线程调用改造网络服务。
【解决方案2】:
  1. 添加

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

进入 Modules Build gradle 的依赖部分

  1. 创建一个像
  2. 这样的 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();
    }
}

【讨论】:

    【解决方案3】:

    在ActivityReceiver类里面,替换

    EventBus.getDefault().register(this); 
    

    EventBus.getDefault().register(this, MyEvent.class);
    

    【讨论】:

    • 它显示了 EventBus 类型的方法 registerSticky(Object, Class>, Class>...) 已弃用
    【解决方案4】:

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

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

    EventBus.getDefault().register(this); 
    

    在你到达这里之前:

    EventBus.getDefault().post(event);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-03
      • 1970-01-01
      相关资源
      最近更新 更多