Ошибка 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
.
Ответы
Ответ 1
У меня была такая же проблема. В некоторых случаях экземпляр оставался зарегистрированным в автобусе. Надежным решением является использование методов onStart()
/onStop()
для регистрации/отмены регистрации приемников. Это то, что предлагают квадратные парни. Они объясняют это так. Если активность находится в фоновом режиме, в любом случае не требуется обновлять пользовательский интерфейс, поскольку пользовательский интерфейс не отображается. После того, как активность начнется на переднем плане, он получит обновление и обновление интерфейса.
Обновление:, как указано в комментариях, регистрация/отмена регистрации в onResume()
/onPause()
может привести к некоторым нежелательным эффектам в некоторых случаях, например, если есть диалог, отображаемый в вашей деятельности, а затем активность приостанавливается и больше не может принимать события.