Существует ли функция commit, выполняющаяся синхронно и не теряющая состояние в Android
Что проверяют
Проверяют знание семейства методов завершения транзакции фрагментов и понимание, почему обычный commit не выполняется сразу. Вопрос с подвохом: у него есть точный ответ, и человек, который переключал фрагменты руками, называет его сразу, а тот, кто видел только готовый навигационный компонент, начинает рассуждать про базы данных.
Как отвечать
Ответ: commitNow(). Он выполняет транзакцию синхронно, прямо в текущем вызове, и при этом остаётся строгим к состоянию, то есть бросит исключение, если менеджер фрагментов уже сохранил состояние.
Разложите всё семейство:
commit(): транзакция ставится в очередь главного потока и выполнится позже; послеonSaveInstanceStateбросаетIllegalStateException;commitNow(): то же самое, но синхронно и только для этой транзакции, отложенные не трогает;commitAllowingStateLoss()иcommitNowAllowingStateLoss(): исключения не будет, но изменение может не пережить пересоздание экрана;executePendingTransactions(): выгоняет очередь целиком, применяется после обычногоcommit, когда фрагмент нужен прямо сейчас.
Важное ограничение назовите сами: commitNow несовместим с addToBackStack, потому что выполнение вне очереди сломало бы порядок стека возврата, и на попытке совместить будет исключение.
Если разговор уходит в SharedPreferences, там своя пара: commit() пишет на диск синхронно и возвращает результат, apply() отдаёт управление сразу, а запись уходит в фон.
Где спотыкаются
Ставят commitAllowingStateLoss везде, где падало. Исключение пропадает, а вместе с ним и сообщение о реальной проблеме: транзакция запускается из колбэка, который приходит после сохранения состояния, и правильное лечение это перенести её в подходящий момент жизненного цикла.
Ждут, что сразу после commit фрагмент найдётся через findFragmentByTag. Не найдётся: транзакция ещё в очереди. Нужен либо commitNow, либо executePendingTransactions.
Ищут commit в работе с базой. У SQLiteDatabase такого метода нет вовсе, транзакция закрывается парой setTransactionSuccessful и endTransaction в блоке finally, и подмена одного другим выглядит как незнание платформы.