Widziałem dwie ogólne praktyki tworzenia nowego fragmentu w aplikacji:
Fragment newFragment = new MyFragment();
i
Fragment newFragment = MyFragment.newInstance();
Druga opcja wykorzystuje metodę statyczną newInstance()
i ogólnie zawiera następującą metodę.
public static Fragment newInstance()
{
MyFragment myFragment = new MyFragment();
return myFragment;
}
Na początku myślałem, że główną korzyścią jest to, że mogę przeciążać metodę newInstance (), aby zapewnić elastyczność podczas tworzenia nowych instancji Fragmentu - ale mogę to również zrobić, tworząc przeciążony konstruktor Fragmentu.
Przegapiłem coś?
Jakie są zalety jednego podejścia względem drugiego? Czy to tylko dobra praktyka?
android
android-fragments
Graham Smith
źródło
źródło
Odpowiedzi:
Jeśli Android zdecyduje się później odtworzyć Fragment, wywoła konstruktor fragmentu bez argumentu. Przeciążenie konstruktora nie jest rozwiązaniem.
Biorąc to pod uwagę, sposobem przekazywania rzeczy do Fragmentu, aby były one dostępne po odtworzeniu Fragmentu przez Androida, jest przekazanie pakietu do
setArguments
metody.Na przykład, jeśli chcielibyśmy przekazać liczbę całkowitą do fragmentu, użylibyśmy czegoś takiego:
Później we fragmencie
onCreate()
możesz uzyskać dostęp do tej liczby całkowitej, używając:Ten pakiet będzie dostępny, nawet jeśli fragment zostanie w jakiś sposób odtworzony przez system Android.
Uwaga:
setArguments
można wywołać tylko przed dołączeniem fragmentu do działania.To podejście jest również udokumentowane w odnośniku dla programistów Androida: https://developer.android.com/reference/android/app/Fragment.html
źródło
Jedyne korzyści z korzystania z
newInstance()
tego, co widzę, są następujące:Będziesz miał jedno miejsce, w którym wszystkie argumenty użyte przez fragment mogą być spakowane i nie musisz pisać kodu poniżej za każdym razem, gdy utworzysz fragment.
Jest to dobry sposób, aby powiedzieć innym klasom, jakich argumentów oczekuje wiernie działać (chociaż powinieneś być w stanie obsługiwać przypadki, jeśli w instancji fragmentu nie ma żadnego argumentu).
Uważam więc, że
newInstance()
dobrym pomysłem jest użycie elementu statycznego do utworzenia fragmentu.źródło
Jest też inny sposób:
źródło
instantiate()
Creates a new instance of a Fragment with the given class name. This is the same as calling its empty constructor.
Podczas gdy @yydl daje przekonujący powód, dla którego
newInstance
metoda jest lepsza: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łączeniasetArguments()
), do którego można uzyskać dostępYourFragment
. Argumentybundle
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 :Jednak konstruktor:
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:Jako dalsze wyjaśnienie, oto klasa fragmentów Androida:
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.źródło
Nie zgadzam się z odpowiedzią yydi mówiącą:
Myślę, że to rozwiązanie i dobre, to jest właśnie powód, dla którego został opracowany przez podstawowy język Java.
Prawdą jest, że system Android może zniszczyć i odtworzyć Twoje
Fragment
. Możesz to zrobić:Pozwoli ci to kontynuować
someInt
odgetArguments()
ostatniego, nawet jeśliFragment
zostały odtworzone przez system. To jest bardziej eleganckie rozwiązanie niżstatic
konstruktor.Moim zdaniem
static
konstruktory są bezużyteczne i nie powinny być używane. Ograniczą cię również, jeśli w przyszłości chcesz to rozszerzyćFragment
i dodać więcej funkcji do konstruktora. Zstatic
konstruktorem nie możesz tego zrobić.Aktualizacja:
System Android dodał inspekcję, która oznacza błąd wszystkich konstruktorów innych niż domyślne.
Polecam ją wyłączyć z wyżej wymienionych powodów.
źródło
Niektóre kody kotlin :
I możesz uzyskać z tym argumenty:
źródło
Najlepszą praktyką w przypadku instancji fragmentów z argumentami w Androidzie jest posiadanie statycznej metody fabrycznej we fragmencie.
Należy unikać ustawiania pól za pomocą instancji fragmentu. Ponieważ ilekroć system Android odtworzy Twój fragment, jeśli poczuje, że system potrzebuje więcej pamięci, wówczas odtworzy Twój fragment przy użyciu konstruktora bez argumentów.
Więcej informacji o najlepszych praktykach tworzenia instancji fragmentów z argumentami znajduje się tutaj.
źródło
Ponieważ mam pytania dotyczące najlepszych praktyk, dodam, że bardzo często dobrym pomysłem jest zastosowanie podejścia hybrydowego do tworzenia fragmentu podczas pracy z niektórymi usługami sieciowymi REST
Nie możemy przekazać złożonych obiektów, na przykład niektórych modeli użytkownika, na wypadek wyświetlenia fragmentu użytkownika
Ale co możemy zrobić, to zarejestrować
onCreate
tego użytkownika! = Null, a jeśli nie - to zabierz go z warstwy danych, w przeciwnym razie - użyj istniejącego.W ten sposób zyskujemy zarówno zdolność do odtwarzania przez userId w przypadku odtwarzania fragmentów przez system Android, jak i snappiness do akcji użytkownika, a także możliwość tworzenia fragmentów przez trzymanie się obiektu lub samego jego identyfikatora
Coś lubi to:
źródło
User user = /*...*/
umieść użytkownika w pakiecie:Bundle bundle = new Bundle(); bundle.putParcelable("some_user", user);
i uzyskaj użytkownika z argumentów:User user = getArguments().getParcelable("some_user");
Obiekt musi być zaimplementowany Interfejs działki. linkużyj tego kodu w 100% napraw swój problem
wprowadź ten kod w firstFragment
ta próbka wysyła dane logiczne
oraz w SecendFragment
szczęśliwy kod
źródło
Najlepszym sposobem na utworzenie instancji fragmentu jest użycie domyślnej metody Fragment.instantiate lub utworzenie metody fabrycznej w celu utworzenia instancji fragmentu
Uwaga: zawsze twórz jeden pusty konstruktor w innym fragmencie, a przywrócenie pamięci fragmentu spowoduje wygenerowanie wyjątku w czasie wykonywania.
źródło
Ostatnio tu jestem. Ale coś, co właśnie wiedziałem, może ci trochę pomóc.
Jeśli korzystasz z Javy, nie musisz wiele zmieniać. Ale dla deweloperów kotlin, oto poniższy fragment, który moim zdaniem może sprawić, że będziesz piwnicą:
Szczęśliwego kodowania.
źródło
setArguments()
jest bezużyteczny. To tylko wprowadza bałagan.źródło
onViewCreated
zakresu. Myślę, że to wygoda, wiele sposobów na zrobienie tego samego. Jest to także łatwy sposób na sprawdzenie, czy użytkownik wykonał aktualizacje (porównaj pakietygetArguments
i pakiet zonSaveInstanceState
)getArguments
elementów. Co zonViewCreated
zakresem ... Możemy przywrócić tam pakiet stanu. Ale ja po prostu wolę dokonaćonCreateView
lekkiej i szybkiej i wykonać całą ciężką inicjalizację wewnątrz,onActivityCreated
ponieważFragment.getActivity()
czasami lubię wracaćnull
i ze względu naonAttach()
zmiany w nowej wersji API 23.set
iget
Arguments
dosaveInstanceState
. Zasadniczo robisz to samo, co dzieje się „pod maską”saveInstanceState
to „pod maską”. Korzystanie zArguments
funkcji duplikowania powoduje, że sprawdzasz dwukrotnie: najpierwArguments
wartości, a potemsaveInstanceState
wartości. Ponieważ musisz użyć wsaveInstanceState
jakikolwiek sposób. Co zArguments
... nie są konieczne.Wierzę, że mam na to rozwiązanie o wiele prostsze.
źródło