Подтвердить что ты не робот

Ошибка IllegalArgumentException с шиной событий Otto в экземпляре фрагмента

Я использую шину событий Otto для подписки на определенные события в ListFragment. Экземпляр шины хранится и создается в подклассе приложения, другими словами, он должен работать как одиночный. Кажется, это не случай...

Фрагмент регистрируется на шине в 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();
    }
}

UPDATE:

Я оставил важную деталь; фрагменты использовались в ViewPager. Они создаются по требованию, когда пользователи перемещаются между страницами в ViewPager. Эта незначительная деталь кажется изменением жизненного цикла фрагментов на некоторых устройствах: onActivityCreated() никогда не вызывается для фрагментов, инициированных после создания ViewPager.

4b9b3361

Ответ 1

У меня была такая же проблема. В некоторых случаях экземпляр оставался зарегистрированным в автобусе. Надежным решением является использование методов onStart()/onStop() для регистрации/отмены регистрации приемников. Это то, что предлагают квадратные парни. Они объясняют это так. Если активность находится в фоновом режиме, в любом случае не требуется обновлять пользовательский интерфейс, поскольку пользовательский интерфейс не отображается. После того, как активность начнется на переднем плане, он получит обновление и обновление интерфейса.

Обновление:, как указано в комментариях, регистрация/отмена регистрации в onResume()/onPause() может привести к некоторым нежелательным эффектам в некоторых случаях, например, если есть диалог, отображаемый в вашей деятельности, а затем активность приостанавливается и больше не может принимать события.