Intereting Posts
Android – камера как детектор движения Когда это происходит? и почему? Действие приложения Android, которое выключение 2.3.3 эмулятор с ошибкой Создайте SDK (один файл jar) с файлами «so» Android Studio не может найти мое устройство Печать штрих-кода с использованием термопринтера Android Как предотвратить появление в моей деятельности мягкой клавиатуры? Android: Как организовать ресурсы проекта? Ошибка keytool: java.security.UnrecoverableKeyException: невозможно восстановить ключевой андроид Listview с заголовком и нижним колонтитулом Удаление регистрации из производственного кода в Android? FragmentStatePagerAdapter с ChildFragmentManager – FragmentManagerImpl.getFragment приводит к исключению NullPointerException Как установить colspan в ячейке gridview андроида Исключительное исключение из режима прерывания для Android Карты Google V2 показывают белый экран Где я могу создать и использовать ScheduledThreadPoolExecutor, TimerTask или Handler?

OnClick или onItemClick при приостановке результатов в "IllegalStateException: не удается выполнить это действие после onSaveInstanceState"

У меня есть TabActivity котором размещается 5x FragmentActivity . Некоторые из них содержат кнопки или списки, которые в своих onClick() или onItemClick() создают и нажимают новый фрагмент.

По большей части это прекрасно работает, но если что-то немного не отвечает, или тестер делает что-то глупое (нажмите и удерживайте кнопку или элемент списка, используйте другой палец для переключения вкладок, затем отпустите кнопку / список – 100% воспроизводимый), я получаю событие click после того, как действие приостановлено и сохранено. См. Фрагмент журнала:

 10-30 17:05:16.258 3415 3415 D BKC DEBUG: More.onSaveInstanceState() 10-30 17:05:16.258 3415 3415 D BKC DEBUG: MoreFragment.onPause() 10-30 17:05:17.309 3415 3415 D BKC DEBUG: MoreFragment.onItemClick() 

Прочитав эту статью и различные вопросы StackOverflow о потере состояния фрагмента, я не вижу правильного ответа на вопрос об этом.

  • Использование commitAllowingStateLoss() (безоговорочно) является обходным commitAllowingStateLoss() которое может скрыть настоящие ошибки.
  • Я не уверен, что OnClickListener регистрации OnClickListener s и OnItemClickListener s в onSaveInstanceState 100% предотвратит это, и это своего рода PITA, чтобы сделать это для каждой кнопки в каждом фрагменте.
  • Кто-то предложил проверить соответствующий фрагмент isAdded() , но я могу подтвердить, что он не работает.
  • Я могу установить флаг в onSaveInstanceState() и onRestoreInstanceState() и проверить это в onClick (), но опять же, это просто kludge. EDIT: О, у фрагмента нет onRestoreInstanceState() , но я могу onResume() флаг в onResume() или что-то еще.

Есть ли правильное решение для этого, что я пропал без вести, или я должен просто пойти с моим выбором?

Solutions Collecting From Web of "OnClick или onItemClick при приостановке результатов в "IllegalStateException: не удается выполнить это действие после onSaveInstanceState""

commitAllowingStateLoss() об этом еще немного, я считаю, что commitAllowingStateLoss() на самом деле является правильным ответом для этого случая. Мы знаем, что мы находимся в обработчике onItemClick() onClick() или onItemClick() , поэтому, если потеря состояния может произойти, мы знаем, что это из-за этого отверстия, которое позволяет событиям щелчка через onSaveInstanceState() .

В моем случайном тестировании новый фрагмент будет всплывать, когда вы вернетесь к соответствующей вкладке, так как ничто фактически не было снесено. Это немного удивительно для пользователя, но, вероятно, приемлемо для этого случая.

Я думаю, что более элегантным решением было бы просто проигнорировать событие click. Настройте очень простой логический флаг в BaseActivity, чтобы отслеживать, когда ваша активность приостановлена:

 class BaseActivity extends BaseFragmentActivity { private boolean isPaused; @Override protected void onPause() { isPaused = true; super.onPause(); } @Override protected void onResume() { super.onResume(); isPaused = false; } public boolean isPaused() { return isPaused; } } 

Всякий раз, когда вы получаете событие click, просто проверьте, приостановлена ​​ли ваша активность. Если это так, то очень безопасно игнорировать событие, так как нет смысла действовать на нем.

 @Override public void onItemClick(AdapterView parent, View view, int position, long id) { if (isPaused()) { //But... we're paused. Ignore. return; } //Act upon legitimate click events here } 

Я могу подтвердить, что это проблема в библиотеке поддержки, а не в вашем коде. Лучшим обходным решением является (вероятно) использование ответа, данного @Doge, который должен отслеживать приостановленное состояние самостоятельно.

Причина, по которой это проблема в библиотеке поддержки, заключается в том, что onClicks происходит после выпуска клика. Если вы используете несколько пальцев, вы можете освободить другое событие щелчка где-нибудь еще (например, другую кнопку), которая изменяет фрагмент. Библиотека поддержки получает свое событие щелчка после изменения фрагмента и не проверяет, все ли оно на переднем плане. Это означает, что вы должны проверить это самостоятельно.

Это означает, что любой вызов setCurrentTab() или setCurrentTabByTag() должен включать проверку приостановленного состояния, если он хочет избежать этого сбоя. Пожалуйста, поправьте меня, если я ошибаюсь.

Поскольку действие приостановлено, и на самом деле нет правильного действия, чтобы взять вещь, которая была выбрана, возможно, самое лучшее действие – поймать и съесть IllegalStateException. Пусть пользовательский интерфейс сделает то, что было в процессе выполнения, и пусть FragmentTransaction падает на пол.