Jaka jest różnica między FragmentPagerAdapter
i FragmentStatePagerAdapter
?
O FragmentPagerAdapter
przewodniku Google mówi:
Ta wersja pagera jest najlepsza do użycia, gdy istnieje garść zwykle bardziej statycznych fragmentów, które należy przełożyć, takich jak zestaw zakładek. Fragment każdej strony odwiedzanej przez użytkownika będzie przechowywany w pamięci, chociaż jej hierarchia widoków może zostać zniszczona, gdy nie będzie widoczna. Może to spowodować użycie znacznej ilości pamięci, ponieważ instancje fragmentów mogą utrzymać dowolną liczbę stanów. W przypadku większych zestawów stron należy rozważyć
FragmentStatePagerAdapter
.
Oraz o FragmentStatePagerAdapter
:
Ta wersja pagera jest bardziej przydatna, gdy istnieje duża liczba stron, które działają bardziej jak widok listy. Gdy strony nie są widoczne dla użytkownika, cały ich fragment może zostać zniszczony, zachowując jedynie zapisany stan tego fragmentu. Dzięki temu pager może zatrzymać znacznie mniej pamięci związanej z każdą odwiedzaną stroną w porównaniu
FragmentPagerAdapter
z kosztem potencjalnie większego obciążenia przy przełączaniu między stronami.
Mam więc tylko 3 fragmenty. Ale wszystkie z nich są osobnymi modułami z dużą ilością danych.
Fragment1
obsługuje niektóre dane (które wprowadzają użytkownicy) i przekazuje je poprzez aktywność do Fragment2
, co jest po prostu proste ListFragment
. Fragment3
jest również ListFragment
.
Więc moje pytania brzmią : Którego adaptera powinienem użyć? FragmentPagerAdapter
czy FragmentStatePagerAdapter
?
źródło
FragmentPagerAdapter
iFragmentStatePagerAdapter
co jestFragmentStateAdapter
?Odpowiedzi:
Jak mówią doktorzy, pomyśl o tym w ten sposób. Jeśli miałbyś zrobić aplikację taką jak czytnik książek, nie będziesz chciał ładować wszystkich fragmentów na raz. Chcesz ładować i niszczyć,
Fragments
gdy użytkownik czyta. W takim przypadku użyjeszFragmentStatePagerAdapter
. Jeśli po prostu wyświetlasz 3 „zakładki”, które nie zawierają dużej ilości ciężkich danych (np.Bitmaps
),FragmentPagerAdapter
Może Ci się to dobrze przydać. Należy również pamiętać, żeViewPager
domyślnie ładuje 3 fragmenty do pamięci. PierwszeAdapter
, o którym wspominasz, może zniszczyćView
hierarchię i ponownie załadować ją w razie potrzeby, drugieAdapter
tylko zapisuje stanFragment
i całkowicie niszczy, jeśli użytkownik wróci do tej strony, stan zostanie przywrócony.źródło
FragmentPagerAdapter
korzystania z niego.FragmentPagerAdapter
że przełączanie między fragmentami może być znacznie szybsze, ponieważ rzeczywisteFragment
obiekty nie muszą być przebudowywane za każdym razem. Z drugiej strony skończyłoby się to użyciem większej ilości pamięci, która utrzymywałaby fragmenty obiektów w pamięci.viewPager.setOffscreenPageLimit(2)
.FragmentPagerAdapter
przechowuje cały fragment w pamięci i może zwiększyć obciążenie pamięci, jeśli zostanie użyta duża liczba fragmentówViewPager
.W przeciwieństwie do jego rodzeństwa,
FragmentStatePagerAdapter
przechowuje tylko zapisaną częśćInstanceState fragmentów i niszczy wszystkie fragmenty, gdy stracą ostrość.Dlatego
FragmentStatePagerAdapter
należy go stosować, gdy musimy używać fragmentów dynamicznych, takich jak fragmenty z widżetami, ponieważ ich dane mogą być przechowywane w.savedInstanceState
Nie wpłynie to również na wydajność, nawet jeśli istnieje duża liczba fragmentów.Przeciwnie,
FragmentPagerAdapter
należy użyć jego rodzeństwa, gdy musimy zapisać cały fragment w pamięci.Kiedy mówię, że cały fragment jest przechowywany w pamięci, oznacza to, że jego instancje nie zostaną zniszczone i utworzą narzut pamięci. Dlatego zaleca się stosowanie
FragmentPagerAdapter
tylko w przypadku małej liczby fragmentówViewPager
.Byłoby jeszcze lepiej, gdyby fragmenty były statyczne, ponieważ nie miałyby dużej liczby obiektów, których instancje byłyby przechowywane.
Aby być bardziej szczegółowym,
FragmentStatePagerAdapter:
z
FragmentStatePagerAdapter
, Twój niepotrzebny fragment zostanie zniszczony. Transakcja jest zobowiązana do całkowitego usunięcia fragmentu z Twojej aktywnościFragmentManager
.Stan
FragmentStatePagerAdapter
pochodzi z faktu, że ocali fragment twojego fragmentuBundle
przedsavedInstanceState
zniszczeniem. Gdy użytkownik przejdzie wstecz, nowy fragment zostanie przywrócony przy użyciu stanu fragmentu.FragmentPagerAdapter:
Przez porównanie
FragmentPagerAdapter
nie robi nic takiego, gdy fragment nie jest już potrzebny.FragmentPagerAdapter
wywołujedetach(Fragment)
transakcję zamiastremove(Fragment)
.To zniszczenie jest widokiem fragmentu, ale pozostawia instancję fragmentu żywą w.
FragmentManager
Więc fragmenty utworzone wFragmentPagerAdapter
nie są nigdy niszczone.źródło
Oto cykl życia dziennika każdego fragmentu, w
ViewPager
którym znajdują się 4 fragmenty ioffscreenPageLimit = 1 (default value)
FragmentStatePagerAdapter
Idź do Fragment1 (uruchomienie działania)
Idź do Fragment2
Idź do Fragment 3
Idź do Fragment 4
FragmentPagerAdapter
Idź do Fragment1 (uruchomienie działania)
Idź do Fragment2
Idź do Fragment 3
Idź do Fragment 4
Wniosek :
FragmentStatePagerAdapter
zadzwoń,onDestroy
gdy Fragment zostanie pokonany,offscreenPageLimit
aFragmentPagerAdapter
nie.Uwaga : Myślę, że powinniśmy używać
FragmentStatePagerAdapter
tej,ViewPager
która ma dużo stron, ponieważ będzie to dobre dla wydajności.Przykład stanowi
offscreenPageLimit
:Jeśli idziemy do Fragment3, to będzie detroy Fragment1 (lub Fragment5 jeśli mają), ponieważ
offscreenPageLimit = 1
. Jeśli ustawimyoffscreenPageLimit > 1
, nie zniszczy.Jeśli w tym przykładzie ustawimy
offscreenPageLimit=4
, nie ma różnicy między używaniemFragmentStatePagerAdapter
lubFragmentPagerAdapter
ponieważ Fragment nigdy nie wywołujeonDestroyView
ionDestroy
kiedy zmieniamy tabulacjęDemo Github tutaj
źródło
Coś, co nie zostało wyraźnie powiedziane w dokumentacji lub w odpowiedziach na tej stronie (nawet sugerowanej przez @Naruto), jest to, że
FragmentPagerAdapter
nie zaktualizuje Fragmentów, jeśli dane w Fragmentie zmienią się, ponieważ zachowuje Fragment w pamięci.Więc nawet jeśli masz ograniczoną liczbę fragmentów do wyświetlenia, jeśli chcesz móc odświeżyć swoje fragmenty (np. Ponownie uruchom zapytanie w celu zaktualizowania listView w fragmencie), musisz użyć FragmentStatePagerAdapter.
Chodzi mi o to, że liczba Fragmentów i to, czy są one podobne, nie zawsze jest kluczowym aspektem do rozważenia. Kluczowe jest także to, czy Twoje fragmenty są dynamiczne.
źródło
FragmentPagerAdapter
w mojej działalności, która korzysta z ViewPager, aby pokazać dwa fragmenty - gdzie każdy fragment zawiera listę. Moja pierwsza lista to „Wszystkie raporty”, a druga lista to „Ulubione raporty”. Na pierwszej liście, jeśli stuknę ikonę gwiazdki dla raportu, aktualizuje on bazę danych, aby przełączać ulubiony status tego raportu. Następnie przesuwam palcem po ekranie i z powodzeniem widzę ten raport w interfejsie użytkownika drugiej listy. Może więc instancje są przechowywane w pamięci, ale w niektórych przypadkach (np. Moje) zawartość faktycznie zaktualizuje się dobrze dla FragmentPagerAdapterFragmentPagerAdapter
przechowuje poprzednie dane, które są pobierane z adaptera, a przy każdymFragmentStatePagerAdapter
uruchomieniu pobiera nową wartość z adaptera.źródło
FragmentStatePagerAdapter = Aby pomieścić dużą liczbę fragmentów w ViewPager. Ponieważ ten adapter niszczy fragment, gdy nie jest on widoczny dla użytkownika i tylko zapisany parametrInstanceState fragmentu jest przechowywany do dalszego wykorzystania. W ten sposób wykorzystywana jest niewielka ilość pamięci i lepsza wydajność w przypadku fragmentów dynamicznych.
źródło
FragmentPagerAdapter : fragment każdej strony odwiedzanej przez użytkownika zostanie zapisany w pamięci, chociaż widok zostanie zniszczony. Kiedy strona będzie ponownie widoczna, widok zostanie odtworzony, ale instancja fragmentu nie zostanie odtworzona. Może to spowodować znaczne zużycie pamięci. FragmentPagerAdapter powinien być używany, gdy potrzebujemy przechowywać cały fragment w pamięci. Wywołania FragmentPagerAdapter odłączają (Fragment) w transakcji zamiast usuwać (Fragment).
FragmentStatePagerAdapter : instancja fragmentu jest niszczona, gdy nie jest widoczna dla użytkownika, z wyjątkiem stanu zapisanego fragmentu. Powoduje to użycie niewielkiej ilości pamięci i może być przydatne do obsługi większych zestawów danych. Powinien być stosowany, gdy musimy korzystać z fragmentów dynamicznych, takich jak fragmenty z widżetami, ponieważ ich dane mogą być przechowywane w saveInstanceState. Nie wpłynie to również na wydajność, nawet jeśli jest ich dużo.
źródło