Как работают транзакции в фрагментах Android
Что проверяют
Знаете ли вы, что происходит между commit() и появлением фрагмента на экране: асинхронность, back stack, связь с жизненным циклом. Следом спрашивают, откуда берётся IllegalStateException после onSaveInstanceState и чем commit() отличается от commitNow().
Как отвечать
Транзакция это набор операций над фрагментами, которые FragmentManager применяет как одно целое. В Activity берут supportFragmentManager, внутри фрагмента childFragmentManager для вложенных и parentFragmentManager для соседей.
- операции:
add,remove,replace(убирает всё из контейнера и добавляет новый),show/hide,attach/detach,setMaxLifecycle; commit(): не выполняет транзакцию сразу, а ставит её в очередь главного потока. Нужен результат немедленно:commitNow()илиexecutePendingTransactions();addToBackStack(name): в стек кладётся сама транзакция, а не фрагмент, иpopBackStack()проигрывает её в обратную сторону. Заменённый фрагмент при этом не уничтожается, у него уничтожается только view (onDestroyView). Без стека он доходит доonDestroy;setReorderingAllowed(true): разрешает менеджеру оптимизировать цепочку операций, документация советует ставить его всегда.
Для контейнера используйте FragmentContainerView, а не FrameLayout. Navigation Component под капотом делает те же транзакции.
Про состояние: после onSaveInstanceState менеджер уже сохранил состояние, новая транзакция в него не попадёт, поэтому commit() бросает исключение. commitAllowingStateLoss() это осознанное согласие потерять изменение, а не лекарство.
Где спотыкаются
Добавляют фрагмент в onCreate без проверки savedInstanceState == null. После поворота система восстанавливает старый фрагмент сама, и поверх него ложится второй.
Вызывают commitNow() вместе с addToBackStack(). Так нельзя, будет IllegalStateException: синхронное выполнение ломает порядок стека относительно отложенных транзакций.
Коммитят транзакцию из колбэка сети, который пришёл после сворачивания приложения. Лучше запускать навигацию из состояния, наблюдаемого с учётом жизненного цикла, а не глушить ошибку.