Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

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

Ответ 2

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), будут сохранены для вас и предоставлены любым новым экземплярам, ​​которые (повторно) созданы. Использование статического метода для создания Фрагмента просто обеспечивает простой способ настройки необходимых аргументов, поддерживая конструктор с нулевым аргументом.

Ответ 3

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

  • ваш код создает диалог, вызывающий созданный вами конструктор, и передающий некоторые аргументы в качестве зависимостей.
  • ваш диалог запускается и использует зависимости, которые вы передали, хотя конструктор
  • пользователь закрывает приложение
  • время, и андроид уничтожает фрагмент в свободной памяти
  • пользователь снова открывает приложение.
  • android заново создаст ваше диалоговое окно, на этот раз используя конструктор по умолчанию. Никакие аргументы не будут приняты!
  • Ваше диалоговое окно будет находиться в нежелательном состоянии. Он может попытаться использовать переменные экземпляра, которые вы ожидали пройти через конструктор, но так как их там нет, вы получите исключение с нулевым указателем.

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

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

Ответ 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;
}