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

CommitAllowingStateLoss() в действиях фрагмента

мое приложение использует действия с фрагментами, оно только в портретном режиме, и нет возможности повернуть экран.

Первоначально я использовал метод commit(), но теперь я планирую без разбора изменить их на commitAllowingStateLoss() для действий фрагмента

Есть ли какая-либо причина не без разбора делать это без переоценки каждого отдельного случая, когда я использую фрагмент?

4b9b3361

Ответ 1

Если я правильно понимаю, вы имеете в виду: есть ли какая-нибудь причина НЕ без разбора делать это без переоценки каждого отдельного случая, когда я использую фрагмент?

Ответ: Да, вы не должны этого делать, не пересматривая каждый отдельный случай, когда вы используете фрагмент.

Конечно, предотвращая перезапуски из-за изменений конфигурации (поворот экрана), вы устранили одну из ключевых проблемных областей: пользователь мог бы поворачивать экран ПОСЛЕ обращения к onSaveInstanceState, но ДО commitAllowingStateLoss. В этом случае фрагмент или часть пользовательского интерфейса могут быть потеряны. Для неофициального обсуждения этого вопроса см. Этот post.

Но есть другие ситуации, которые вы должны рассмотреть перед заменой commit на commitAllowingStateLoss.

  • В принципе, любые обновления пользовательского интерфейса между onSaveInstanceState и commitAllowingStateLoss: Android: IllegalStateException - Когда оно выбрано?

  • Если у вас есть обезглавленные фрагменты, обновляющие пользовательский интерфейс вашей деятельности, некоторые из их обновлений могут быть потеряны (см. article).

  • Android может "убить" фрагмент, потому что телефон/вкладка работает на ресурсах (см. этот ответ).

Конечно, если предотвращение вращения экрана невозможно, тогда onSaveInstanceState не может быть вызван, и в этом случае окно возможности для обновления будет увеличено.

Если вы решите использовать commitAllowingStateLoss, то вы можете сделать это, чтобы свести к минимуму риски: рассмотрите возможность выполнения commit/executePendingTransactions, когда родительская активность будет перезапущена (я знаю, что вы не хотите этого делать, но кто-то может прочитать это).

Наконец (опять же, если кто-то еще читает это - это не имеет значения в вашем случае), возможно, более безопасные способы обработки IllegalStateException, чем переход от фиксации к commitAllowStateLoss. например, вы можете просто придерживаться фиксации и обрабатывать IllegalStateException. Кроме того, вы можете использовать ошибку в Android и может быть обходной путь.

Ответ 2

public abstract int commit ()

Запланирует фиксацию транзакции. Конец не происходит немедленно; он будет запланирован, поскольку работа над основным потоком будет выполнена в следующий раз, когда поток будет готов.

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

public abstract int commitAllowingStateLoss ()

Добавлен в уровень API 11

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

FragmentActivity ограничения

До Honeycomb (3.0) состояние активности было сохранено до паузы. Фрагменты представляют собой значительное количество нового состояния и достаточно динамичны, что часто требуется, чтобы они переключались между паузами и остановками. Эти классы генерируют исключение, если вы пытаетесь изменить состояние фрагмента после его сохранения, чтобы избежать случайной потери состояния пользовательского интерфейса. Однако это слишком ограничительно перед Honeycomb, где состояние сохраняется до паузы. Чтобы решить эту проблему, при запуске на платформах до Honeycomb исключение не будет выбрано, если вы измените фрагменты между сохранением состояния и остановленной деятельностью. Это означает, что в некоторых случаях, если активность восстанавливается из последнего сохраненного состояния, это может быть моментальный снимок немного раньше, чем пользователь видел в последний раз.

Итак, если вы не задуманы с потерей государства, я думаю, что ваше решение в порядке. я надеюсь, что это поможет вам с вашим решением.

Ответ 3

Лучшей идеей будет использование commit() в обратных вызовах OnPostResume, а не с помощью commitAllowingStateLoss() без разбора. Следующее blogpost предоставляет подробное объяснение http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html

@Override
protected void onPostResume() {
    super.onPostResume();
    // Commit your transactions here.
}

Ответ 4

try {
    transaction.commit();
} catch (IllegalStateException e) {
    transaction.commitAllowingStateLoss();
}

Ответ 5

Вы можете переопределить следующий метод, подобный этому

@Override
public void supportFinishAfterTransition() {
    finish();
    super.supportFinishAfterTransition();
}

это сработало для меня.

Ответ 6

Использовать commitAllowingStateLoss() только в крайнем случае. Единственная разница между вызовом commit() и commitAllowingStateLoss() заключается в том, что последний не будет генерировать исключение, если происходит потеря состояния. Обычно вы не хотите использовать этот метод, потому что это означает, что существует вероятность того, что потеря состояния может произойти. Лучшее решение, конечно, состоит в том, чтобы написать ваше приложение, чтобы гарантировать, что commit() будет вызван до того, как состояние активности будет сохранено, так как это приведет к лучшему опыту пользователя. Если исключить возможность потери государственной потери, commitAllowingStateLoss() не следует использовать.