Как FragmentManager создает фрагмент и ищет конструктор
Что проверяют
Знаете ли вы, почему фрагменту нужен пустой публичный конструктор и что фрагмент создаёт не только ваш код, но и система при восстановлении. Следом почти всегда спрашивают про FragmentFactory и про то, как передать во фрагмент зависимости.
Как отвечать
Когда вы пишете MyFragment(), конструктор вызываете вы. Но FragmentManager создаёт фрагменты и сам: при восстановлении после смены конфигурации или смерти процесса, при инфлейте FragmentContainerView с атрибутом android:name, при add(R.id.container, MyFragment::class.java, args), в Navigation Component. В этих случаях у него есть только имя класса.
Дальше работает FragmentFactory:
instantiate(classLoader, className): метод, через которыйFragmentManagerполучает новый экземпляр;- реализация по умолчанию: загружает класс по имени и через рефлексию вызывает
getConstructor().newInstance(), то есть ищет публичный конструктор без параметров; - нет такого конструктора: падает
Fragment.InstantiationExceptionс текстом про пустой публичный конструктор. То же будет с непубличным, вложенным нестатическим или анонимным классом; - аргументы:
Bundleизargumentsсохраняется в состоянии и возвращается фрагменту после создания, поэтому данные передают черезarguments, а не через конструктор.
Если зависимости нужны в конструкторе, пишете свою фабрику на базе FragmentFactory и назначаете её: supportFragmentManager.fragmentFactory = MyFactory(repo). Сделать это нужно до super.onCreate() в Activity, потому что восстановление фрагментов происходит внутри него. С Hilt зависимости приходят в поля через @AndroidEntryPoint, и пустой конструктор остаётся.
Где спотыкаются
Говорят, что FragmentManager «просто вызывает new». Это рефлексия по имени класса, отсюда и требования к конструктору.
Назначают fragmentFactory после super.onCreate(). Всё работает до первого поворота экрана, а на восстановлении падает.
Добавляют в Kotlin конструктор, где не у всех параметров есть значения по умолчанию, и тестируют только прямой путь. Ошибка всплывает лишь после смерти процесса, её удобно ловить опцией разработчика «Не сохранять действия».