14

我正在使用 Otto 事件总线订阅 ListFragment 中的某些事件。总线实例存储和创建在 Application 的子类中,换句话说,它总线应该作为单例工作。好像不是这样的……

该片段在 中注册到总线onActivityCreated(Bundle)并在中取消注册onDestroy()。这不能正常工作。我从应用程序在调用时崩溃的设备收到了几份崩溃报告unregister()(java.lang.IllegalArgumentException:缺少带注释的方法的事件处理程序......)。unregister()仅当在任何 register() 调用之前被调用或被unregister()调用两次时才会抛出此异常。这可能只发生在...

  • onActivityCreated(Bundle)之前没有调用onDestroy()
  • onDestroy()被调用两次。
  • 在调用和Application之间重新创建实例。onActivityCreated(Bundle)onDestroy()

我的应用程序类:

public class App extends Application {

    private static App sInstance;

    private Bus bus;

    public static App getInstance() {
        return sInstance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        sInstance = this;
        bus = new Bus(ThreadEnforcer.ANY);
    }

    public Bus getEventBus() {
        return bus;
    }

}

片段类:

public class MyFragment extends ListFragment {

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        App.getInstance().getEventBus().register(this);
    }

    @Subscribe
    public void onEvent(MyEvent event) {
        ....
    }

    @Override
    public void onDestroy() {
        App.getInstance().getEventBus().unregister(this);
        super.onDestroy();
    }
}

更新:

我遗漏了一个重要的细节;片段用于 a ViewPager。当用户在ViewPager. 这个小细节似乎改变了某些设备上的片段生命周期:在创建 onActivityCreated()之后启动的片段永远不会被调用。ViewPager

4

1 回答 1

38

我有同样的问题。在某些情况下,实例保持在总线上注册。一个可靠的解决方案是使用onStart()/onStop()方法来注册/注销接收器。这也是 Square 的人建议的。他们是这样解释的。如果活动在后台,则无论如何都不需要刷新 UI,因为 UI 是不可见的。一旦活动进入前台,它将接收更新并刷新 UI。

更新:如评论中所述,在某些情况下注册/注销onResume()/onPause()可能会导致一些不良影响,例如如果您的活动上显示一个对话框,则活动会暂停并且不再能够接收事件。

于 2013-11-01T23:40:57.947 回答