У меня есть Fragment
с конструктором, который принимает несколько аргументов. Мое приложение работало нормально во время разработки, но на производстве мои пользователи иногда видят этот сбой:
android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment
make sure class name exists, is public, and has an empty constructor that is public
Я мог бы создать пустой конструктор, как следует из этого сообщения об ошибке, но это не имеет смысла для меня с тех пор, как мне пришлось бы вызывать отдельный метод для завершения настройки Fragment
.
Мне любопытно, почему этот сбой случается только изредка. Может я ViewPager
неправильно использую? Я сам создаю все экземпляры Fragment
и сохраняю их в списке внутри Activity
. Я не использую FragmentManager
транзакции, так как ViewPager
примеры, которые я видел, не требовали этого, и все, казалось, работало во время разработки.
android
android-fragments
stkent
источник
источник
Fragment
подкласс вообще не объявляет никаких конструкторов, то по умолчанию для вас неявно создается пустой открытый конструктор (это стандартное поведение Java ). Вам не нужно явно объявлять пустой конструктор, если вы также не объявили другие конструкторы (например, с аргументами).Ответы:
Да, они делают.
В любом случае, вы не должны переопределять конструктор. Вы должны определить
newInstance()
статический метод и передать любые параметры через аргументы (связка)Например:
И, конечно, схватить арги таким образом:
Затем вы должны создать экземпляр из вашего менеджера фрагментов следующим образом:
Таким образом, если отсоединено и повторно присоединено, состояние объекта может быть сохранено через аргументы. Очень похоже на связки, прикрепленные к Intents.
Причина - Дополнительное чтение
Я думал, что объясню, почему людям интересно, почему.
Если вы проверите: https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/Fragment.java
Вы увидите, что
instantiate(..)
метод вFragment
классе вызываетnewInstance
метод:http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#newInstance () Объясняет, почему после создания экземпляра он проверяет, является ли метод доступа
public
и что загрузчик классов разрешает доступ к нему.В целом, это довольно неприятный метод, но он позволяет
FragmentManger
убивать и восстанавливатьFragments
состояния. (Подсистема Android делает схожие вещиActivities
).Пример класса
Меня часто спрашивают о звонке
newInstance
. Не путайте это с методом класса. Весь этот пример класса должен показать использование.источник
Как отмечает CommonsWare в этом вопросе https://stackoverflow.com/a/16064418/1319061 , эта ошибка также может возникать, если вы создаете анонимный подкласс фрагмента, поскольку у анонимных классов не может быть конструкторов.
Не делайте анонимных подклассов фрагмента :-)
источник
Да, как вы можете видеть, пакет поддержки также создает фрагменты (когда они уничтожаются и открываются заново). Вашим
Fragment
подклассам нужен общедоступный пустой конструктор, так как это то, что вызывается фреймворком.источник
super()
, будут бесполезны, так как родительский класс нарушил правило пустого открытого конструктора. Так что нет, вам не нужно проходитьsuper()
внутри вашего конструктора.Вот мое простое решение:
1 - Определите свой фрагмент
2 - Создайте свой новый фрагмент и заполните параметр
3 - Наслаждайся этим!
Очевидно, вы можете изменить тип и количество параметров. Быстро и просто.
источник