Зачем использовать newInstance для DialogFragment вместо конструктора?

Рассматривая документацию DialogFragment , можно увидеть, что статический метод newInstance инициализирует новый фрагмент диалогового окна предупреждения. Мой вопрос: почему бы не использовать конструктор для этого, например:

 public MyAlertDialogFragment(int title) { Bundle args = new Bundle(); args.putInt("title", title); setArguments(args); } 

Разве это не то же самое или оно не так или иначе отличается? Какой лучший подход и почему ?

Если вы перегрузите конструктор с помощью MyAlertDialogFragment(int title) , система Android может по-прежнему вызывать конструктор MyAlertDialogFragment() по умолчанию, если Fragment необходимо воссоздать, а затем параметр не передается.

Android опирается на фрагменты, имеющие открытый конструктор с нулевым аргументом, чтобы он мог воссоздать его в разное время (например, изменения конфигурации, восстановление состояния приложения после того, как он был ранее убит Android и т. Д.).

Если у вас нет такого конструктора (например, вопрос в вопросе), вы увидите эту ошибку при попытке создать экземпляр:

 Fragment$InstantiationException: Unable to instantiate fragment make sure class name exists, is public, and has an empty constructor that is public 

Аргументы, предоставленные ему Fragment.setArguments(Bundle) будут сохранены для вас и предоставлены любым новым экземплярам, ​​которые (повторно) созданы. Использование статического метода для создания Фрагмента просто обеспечивает простой способ настройки необходимых аргументов, сохраняя конструктор с нулевым аргументом.

Если вы создадите DialogFragment, который получает объекты через конструктор, у вас возникнут проблемы, когда андроид воссоздает ваш фрагмент. Вот что произойдет:

  1. Ваш код создает диалог, вызывающий созданный вами конструктор, и передающий некоторые аргументы в качестве зависимостей.
  2. Ваш диалог запускается и использует зависимости, которые вы передали, хотя конструктор
  3. Пользователь закрывает приложение
  4. Время, и андроид убивает фрагмент для освобождения памяти
  5. Пользователь снова откроет приложение
  6. Android заново создаст ваше диалоговое окно, на этот раз используя конструктор по умолчанию. Никакие аргументы не будут приняты!
  7. Ваш диалог будет в нежелательном состоянии. Он может попытаться использовать переменные экземпляра, которые вы ожидали пройти через конструктор, но так как их там нет, вы получите исключение с нулевым указателем.

Чтобы этого избежать, вам не нужно полагаться на конструктор, чтобы устанавливать зависимости, но в Bundles (аргументы и сохраненные экземпляры). Это может заставить вас реализовать Parcelable в некоторых классах, что отстой.

EDIT: вы можете воспроизвести Android, убивающее приложение (шаг 4), включив «Не поддерживать действия» в настройках разработки. Это способ легко протестировать его.

Поскольку, когда андроид воссоздает фрагмент, он всегда использует пустой конструктор, и с помощью newInstance () вы можете установить данные, которые использует фрагмент при воссоздании, например, когда экран повернут

например:

  public static FragmentExample newInstance(Parcelable uri) { FragmentExample fragmentExample = new FragmentExample(); Bundle bundle = new Bundle(); bundle.putParcelable("Uri", uri); fragmentExample.setArguments(bundle); return fragmentExample; }