Как правильно передавать параметры во фрагмент
Что проверяют
Знаете ли вы, что фрагмент может пересоздать система, и переживут ли ваши параметры поворот экрана и смерть процесса. Следом обычно спрашивают, как вернуть результат из фрагмента обратно и что делать с большими объектами.
Как отвечать
Начните с причины. После смены конфигурации или восстановления процесса FragmentManager создаёт фрагмент заново через FragmentFactory, по умолчанию пустым конструктором. Всё, что вы передали в конструктор или сеттер, пропадёт. Сохраняется только arguments, потому что этот Bundle пишется в состояние фрагмента.
- фабричный метод:
newInstance()вcompanion object, внутриarguments = bundleOf(ARG_ID to id); - чтение:
requireArguments().getLong(ARG_ID)вonCreate()или в ViewModel. Стандартная фабрика ViewModel кладёт аргументы фрагмента вSavedStateHandle, так что они доступны там без ручного проброса; - Navigation Component: плагин Safe Args генерирует классы
...Argsи...Directions, а делегатnavArgs()даёт типизированный доступ. Опечатка в ключе становится ошибкой компиляции; - сложные объекты:
Parcelableчерез плагинkotlin-parcelizeи аннотацию@Parcelize. С API 33 старыйgetParcelable(key)помечен устаревшим, используйтеBundleCompat.getParcelable(bundle, key, Class); - обратно: Fragment Result API,
setFragmentResult()иsetFragmentResultListener(), либо общая ViewModel черезactivityViewModels().
Отдельно скажите, что зависимости (репозиторий, аналитику) через Bundle не передают: для них есть DI или своя FragmentFactory с конструктором.
Где спотыкаются
Передают данные через конструктор с параметрами или публичное поле. В отладке всё работает, а после поворота или с включённым «Don’t keep activities» фрагмент падает с InstantiationException или получает пустые данные.
Кладут в аргументы список на тысячи элементов или Bitmap. Буфер транзакций Binder около мегабайта на процесс, и при сохранении состояния прилетает TransactionTooLargeException. Передавайте id, а данные грузите из репозитория.
Меняют arguments у уже добавленного фрагмента: после сохранения состояния setArguments() бросает IllegalStateException.