Podczas gdy @yydl daje przekonujący powód, dla którego newInstance
metoda jest lepsza:
Jeśli Android zdecyduje się później odtworzyć Fragment, wywoła konstruktor fragmentu bez argumentu. Przeciążenie konstruktora nie jest rozwiązaniem.
nadal jest całkiem możliwe użycie konstruktora . Aby zrozumieć, dlaczego tak jest, najpierw musimy dowiedzieć się, dlaczego powyższe obejście jest używane przez system Android.
Przed użyciem fragmentu potrzebna jest instancja. Wywołania Androida YourFragment()
(konstruktor bez argumentów ) w celu skonstruowania instancji fragmentu. Tutaj każdy przeciążony konstruktor, który napiszesz, zostanie zignorowany, ponieważ Android nie może wiedzieć, którego użyć.
W czasie trwania działania fragment jest tworzony jak wyżej i wielokrotnie niszczony przez Androida. Oznacza to, że jeśli umieścisz dane w samym obiekcie fragmentu, zostaną one utracone po zniszczeniu fragmentu.
Aby obejść ten problem, Android prosi o przechowywanie danych za pomocą Bundle
(połączenia setArguments()
), do którego można uzyskać dostęp YourFragment
. Argumenty bundle
są chronione przez system Android, a zatem gwarantuje się, że będą trwałe .
Jednym ze sposobów ustawienia tego pakietu jest użycie newInstance
metody statycznej :
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;
}
Jednak konstruktor:
public YourFragment(int data) {
Bundle args = new Bundle();
args.putInt("data", data);
setArguments(args);
}
może zrobić dokładnie to samo co newInstance
metoda.
Oczywiście to się nie powiedzie i jest to jeden z powodów, dla których Android chce, abyś użył tej newInstance
metody:
public YourFragment(int data) {
this.data = data; // Don't do this
}
Jako dalsze wyjaśnienie, oto klasa fragmentów Androida:
/**
* 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;
}
Pamiętaj, że Android prosi o ustawienie argumentów tylko na etapie budowy i gwarantuje, że zostaną one zachowane.
EDYCJA : Jak wskazano w komentarzach @JHH, jeśli udostępniasz niestandardowy konstruktor, który wymaga pewnych argumentów, wówczas Java nie dostarczy twojemu fragmentowi domyślnego konstruktora bez arg . Wymagałoby to więc zdefiniowania konstruktora no arg , czyli kodu, którego można by uniknąć za pomocą newInstance
metody fabrycznej.
EDYCJA : Android nie pozwala już na używanie przeciążonego konstruktora dla fragmentów. Musisz użyć tej newInstance
metody.