В то время как @yydl дает убедительную причину, почему newInstance
метод лучше:
Если Android решит воссоздать ваш фрагмент позже, он вызовет конструктор без аргументов вашего фрагмента. Таким образом, перегрузка конструктора не является решением.
все еще вполне возможно использовать конструктор . Чтобы понять, почему это так, сначала нам нужно понять, почему вышеуказанный обходной путь используется Android.
Перед использованием фрагмента необходим экземпляр. Android вызывает YourFragment()
( конструктор без аргументов ) для создания экземпляра фрагмента. Здесь любой перегруженный конструктор, который вы напишите, будет игнорироваться, так как Android не может знать, какой из них использовать.
Во время жизни действия фрагмент создается, как описано выше, и несколько раз уничтожается Android. Это означает, что если вы поместите данные в сам объект фрагмента, они будут потеряны после уничтожения фрагмента.
Чтобы обойти эту проблему, Android просит сохранить данные с помощью Bundle
(вызова setArguments()
), к которому затем можно получить доступ YourFragment
. Аргументы bundle
защищены Android, и, следовательно, гарантированно будут постоянными .
Один из способов установить этот комплект - использовать статический newInstance
метод:
public static YourFragment newInstance (int data) {
YourFragment yf = new YourFragment()
/* See this code gets executed immediately on your object construction */
Bundle args = new Bundle();
args.putInt("data", data);
yf.setArguments(args);
return yf;
}
Тем не менее, конструктор:
public YourFragment(int data) {
Bundle args = new Bundle();
args.putInt("data", data);
setArguments(args);
}
может сделать то же самое, что и newInstance
метод.
Естественно, это не удастся, и это одна из причин, по которой Android хочет, чтобы вы использовали этот newInstance
метод:
public YourFragment(int data) {
this.data = data; // Don't do this
}
Как дальнейшее объяснение, вот класс фрагментов Android:
/**
* Supply the construction arguments for this fragment. This can only
* be called before the fragment has been attached to its activity; that
* is, you should call it immediately after constructing the fragment. The
* arguments supplied here will be retained across fragment destroy and
* creation.
*/
public void setArguments(Bundle args) {
if (mIndex >= 0) {
throw new IllegalStateException("Fragment already active");
}
mArguments = args;
}
Обратите внимание, что Android запрашивает, чтобы аргументы устанавливались только при конструировании, и гарантирует, что они будут сохранены.
РЕДАКТИРОВАТЬ : Как указано в комментариях @JHH, если вы предоставляете пользовательский конструктор, который требует некоторых аргументов, то Java не будет предоставлять ваш фрагмент конструктор по умолчанию без аргументов . Так что для этого потребуется определить конструктор без аргументов , то есть код, который вы могли бы избежать с помощью newInstance
метода фабрики.
РЕДАКТИРОВАТЬ : Android больше не позволяет использовать перегруженный конструктор для фрагментов. Вы должны использовать newInstance
метод.